C.W.K.
Stream
Lesson 07 of 08 · published

Broadcasting

~12 min · fastapi, broadcast, exclude, background-task

Level 0Poller
0 XP0/60 lessons0/10 achievements
0/120 XP to next level120 XP to go0% complete

Broadcast variants

Real-world broadcast has three flavors. Room broadcast: send to everyone in a room. Room broadcast excluding sender: avoid echoing back to the user who sent the message. Direct message to a specific user: requires you to also track user_id → WebSocket. Implement all three on your manager and you cover most needs.

Server-initiated push

For periodic updates (price ticker, system metrics, heartbeat broadcast), spin a background task in lifespan startup. Any task that calls manager.broadcast() can run independently of any client request. The task lives for the life of the application.

Code

exclude + send_to_user·python
class ConnectionManager:
    # ... rooms as before ...
    user_map: Dict[str, WebSocket] = {}

    async def broadcast(self, room: str, message: dict, *, exclude: WebSocket | None = None):
        dead = []
        for ws in self.rooms.get(room, set()):
            if ws is exclude:
                continue
            try:
                await ws.send_json(message)
            except Exception:
                dead.append(ws)
        for ws in dead:
            self.disconnect(ws, room)

    async def send_to_user(self, user_id: str, message: dict):
        ws = self.user_map.get(user_id)
        if ws is None:
            return False
        try:
            await ws.send_json(message)
            return True
        except Exception:
            self.user_map.pop(user_id, None)
            return False
Background ticker via lifespan·python
from contextlib import asynccontextmanager
import asyncio
from fastapi import FastAPI

@asynccontextmanager
async def lifespan(app: FastAPI):
    task = asyncio.create_task(price_ticker())
    yield
    task.cancel()

async def price_ticker():
    while True:
        price = await get_latest_btc()
        await manager.broadcast('btc-feed', {
            'type': 'price.update',
            'data': {'symbol': 'BTC', 'price': price},
        })
        await asyncio.sleep(1)

app = FastAPI(lifespan=lifespan)

External links

Exercise

Add send_to_user and broadcast(..., exclude=...) to your manager. Build a chat endpoint where every message broadcasts to the room except the sender; the sender gets a private chat.ack instead. Verify in three browser tabs that the sender sees ack and the other two see chat.message.

Progress

Progress is local-only — sign in to sync across devices.
Spotted a bug or have feedback on this page?Report an Issue

Comments 0

🔔 Reply notifications (sign in)
Sign inPlease sign in to comment.

No comments yet — be the first.