A chat system delivers messages between users in real time, reliably and in order. The interesting parts are the persistent connection model, delivery guarantees, and handling users who are offline.
1. Requirements
- Functional: one-to-one (and group) messaging; delivery/read receipts; online presence; message history.
- Non-functional: low latency, reliable delivery (no lost messages), correct ordering, and support for offline recipients.
2. Real-time transport
Polling is wasteful for chat. Use a persistent connection — typically WebSockets — so the server can push messages to clients instantly. Clients connect to chat servers that hold these long-lived connections; a service tracks which server each online user is connected to.
3. Sending a message
When A messages B: the message hits A's chat server, gets persisted (so it's never lost), then routed to B's chat server, which pushes it over B's WebSocket. Delivery/read receipts flow back the same way. Give each message a sequence ID per conversation to guarantee ordering.
4. Offline users
If B is offline, the message stays in a persistent store / inbox and a push notification is sent. When B reconnects, the client syncs undelivered messages from the store. This is why persistence-before-delivery matters.
5. Presence & storage
Presence (online/last-seen) is tracked via connection state plus heartbeats, cached in something like Redis. Messages are stored in a database optimised for high write volume and per-conversation reads (a wide-column store like Cassandra is a common choice). Group chat fans a message out to all members' inboxes.