Real-Time Chat Server with WebSockets
Build a chat server in Python with asyncio and the websockets library, where people join rooms and chat in real time from their browsers. A single process handles many connections at once without threads, thanks to asyncio. Users pick a name, join rooms, see the last messages when they arrive, and get live updates when others join, leave or write. The server stays healthy when clients misbehave: slow clients can't hold up everyone else, malformed messages are rejected, and disconnects are cleaned up. You'll learn asynchronous programming with async and await, the WebSocket protocol, managing shared state safely in one event loop, backpressure, and testing asynchronous code with pytest.
- Estimate
- ~11.5h
- Steps
- 7
- Completed by
- 0
- Proposed by
- codeseed.app
asyncio · websockets
Project roadmap
- 01
Start the WebSocket server
~1.5hCreate a project with the websockets library. Write an async handler that accepts connections and echoes each message back, and start the server with websockets.serve on a configurable host and port, running until Ctrl+C. Test it with a small Python client or the websockets command-line client. Done when: messages sent to the server come back.
- 02
Define the messages
~1.5hDefine JSON messages from clients: hello (choose a name), join (room), leave (room) and message (room and text), and from the server: welcome, history, message, user_joined, user_left and error. Validate every incoming message (known type, required fields, a name of 1 to 20 allowed characters, text up to 1,000 characters) and answer invalid ones with an error without closing the connection. Done when: invalid messages get clear errors, and valid ones are accepted.
- 03
Broadcast in rooms
~2hKeep a dictionary of rooms to their connected clients, updated only from the event loop so no locks are needed. When a client joins, add them and tell the others; when a message arrives, add the server time and the sender's name and send it to everyone in the room. Refuse duplicate names. Done when: several clients in the same room see each other's messages, and other rooms don't.
- 04
Add history
~1hKeep the last 50 messages of each room in a collections.deque with a maximum length, and send them to a client when they join. Remove a room and its history when the last member leaves (or keep it for a while, as you prefer, and document it). Done when: someone joining a room sees its recent messages in order.
- 05
Handle disconnects and slow clients
~2hClean up a client's rooms when their connection closes, whether normally or with an error (catch ConnectionClosed), and announce that they left. Send to each client through its own asyncio.Queue with a size limit and a sender task, and disconnect clients whose queue fills up, so one slow client never delays the others. Make sure an error with one client never stops the server. Done when: killing a client removes it from its rooms, and a deliberately slow client is dropped without affecting the rest.
- 06
Build a small web client
~1.5hWrite an HTML page with plain JavaScript that connects with the browser's WebSocket API, asks for a name, lets the user join rooms and send messages, and shows history and live messages, displaying text safely (with textContent, never innerHTML). Done when: two browser tabs can chat in the same room.
- 07
Test it
~2hWrite pytest tests with pytest-asyncio that start the server on a free port and connect several clients: joining and broadcasting, room isolation, history on join, validation errors, duplicate names, and cleanup after a disconnect. Done when: pytest passes.
Ready to build this?
Get a GitHub repo and start building. Your AI reviewer checks each step as you go.
Tech stack