FastAPI cookbook · Advanced
Build a WebSocket chat endpoint in FastAPI
Broadcast messages to all users in a room in real time, across multiple app instances.
Approach
Accept WebSocket connections per room, authenticate during the handshake (token query param or cookie), and fan out messages via Redis pub/sub so users connected to different instances receive them. Each connection runs a receive loop and a subscriber task; clean up on disconnect.
Solution
import asyncio, json
from fastapi import WebSocket, WebSocketDisconnect, status
from redis.asyncio import Redis
redis = Redis.from_url("redis://redis:6379/0")
@app.websocket("/ws/rooms/{room_id}")
async def room(websocket: WebSocket, room_id: str):
user = await authenticate_ws(websocket) # e.g. validate token from the cookie or a query param
if user is None:
await websocket.close(code=status.WS_1008_POLICY_VIOLATION)
return
await websocket.accept()
pubsub = redis.pubsub()
await pubsub.subscribe(f"room:{room_id}")
async def forward_from_redis():
async for message in pubsub.listen():
if message["type"] == "message":
await websocket.send_text(message["data"].decode())
forwarder = asyncio.create_task(forward_from_redis())
try:
while True:
text = (await websocket.receive_text())[:2000]
payload = json.dumps({"user": user.name, "text": text})
await redis.publish(f"room:{room_id}", payload)
except WebSocketDisconnect:
pass
finally:
forwarder.cancel()
await pubsub.unsubscribe(f"room:{room_id}")
await pubsub.aclose()
Pitfalls
- In-memory connection lists that only work on a single instance.
- No authentication or authorization per room.
- Unbounded message sizes and rates (add limits).
Variations
- Persist messages to a database for history; pub/sub is fire-and-forget.
- Use Redis Streams or a managed service when delivery guarantees matter.
Further reading: FastAPI: WebSockets
Reference: https://fastapi.tiangolo.com/advanced/websockets/
More FastAPI recipes
- Add liveness and readiness endpoints to FastAPI
- Add OpenTelemetry tracing to FastAPI
- Add request IDs and structured logs to FastAPI
- Cache FastAPI responses in Redis
- Call external APIs with retries and timeouts from FastAPI
- Implement role-based access control in FastAPI
- Isolate tenants in a multi-tenant FastAPI app
- Paginate with cursors in FastAPI