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

Rooms & Channels

~12 min · management, rooms, channels

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

Rooms are server-side groupings

A "room" is just an arbitrary string the server uses to group connections. Send to that string; everyone subscribed to it receives. The browser does not know rooms exist — the server is the gatekeeper.

Switching rooms cleanly

Letting a user move between rooms within one connection is a powerful UX (Slack, Discord). The server pattern is: receive a switch_room message → disconnect from the manager (preserves the WebSocket itself) → connect again with the new room. The same physical connection, two logical memberships.

Channels vs. rooms

Some libraries distinguish "rooms" (loose groupings) from "channels" (named, often persistent broadcast topics). The implementation is identical; the distinction is conceptual. Pick one term and stay consistent in your codebase.

Code

Room-based handler with switch support·python
@app.websocket('/ws/{room}')
async def chat(websocket: WebSocket, room: str):
    user_id = websocket.query_params.get('user_id', 'anon')
    await manager.connect(websocket, user_id, room)

    await manager.broadcast(room, {
        'type': 'user.joined',
        'data': {'user_id': user_id, 'room': room,
                 'online': manager.room_users(room)},
    }, exclude=websocket)

    try:
        async for msg in websocket.iter_json():
            t = msg.get('type')
            if t == 'switch_room':
                old_room = manager.ws_meta[websocket]['room']
                new_room = msg['data']['room']
                manager.disconnect(websocket)
                await manager.connect(websocket, user_id, new_room)
                await manager.broadcast(old_room, {
                    'type': 'user.left',
                    'data': {'user_id': user_id},
                })
            elif t == 'chat.message':
                await manager.broadcast(
                    manager.ws_meta[websocket]['room'],
                    {'type': 'chat.message', 'data': {**msg['data'], 'from': user_id}},
                    exclude=websocket,
                )
    except WebSocketDisconnect:
        room = manager.ws_meta.get(websocket, {}).get('room', room)
        manager.disconnect(websocket)
        await manager.broadcast(room, {
            'type': 'user.left',
            'data': {'user_id': user_id},
        })

External links

Exercise

Build a UI with a sidebar of rooms (general, random, support). Clicking a room sends switch_room over the existing WebSocket. Verify in dev tools that no new WebSocket connection opens — the same one is reused.

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.