Chat System
Team chat with channels and history
Design a team chat service with channels and direct messages that shows everyone the same message order, keeps full searchable history, and tracks presence, unread counts and who has read what.
Overview
A team chat service carries conversations in channels (a team, a project, a topic) and in direct messages. Unlike a phone messenger that only relays messages, it keeps the full history on the server: people join a channel and scroll back months, open it on a second laptop, and search it.
Keeping history changes the hard parts. Every member must see a channel's messages in the same order, so the server assigns the order. A client that loses its connection for a moment must fill in exactly what it missed. History pages must stay fast deep into a busy channel. And the small signals (who is online, who is typing, who has read what, how many unread) must not cost more than the messages themselves.
Questions to ask first
- How many users and messages? — 20 million daily users, 50 messages each a day
- Channel sizes? — Most under 50 members; some with tens of thousands
- Is history kept on the server? — Yes, forever, and it can be searched
- Several devices per user? — Yes: desktop, web and phone at once
- Read receipts? — Unread counts everywhere; 'read by' shown in small channels and DMs
- Encryption? — TLS in transit and encryption at rest; not end to end (so the server can search)
What you will be able to do
- Route a message to every connected member through gateways and pub/sub.
- Give each channel one order with a server-assigned sequence, and make sends idempotent.
- Recover missed messages after a reconnect with gap detection.
- Page through history with a keyset cursor.
- Track unread counts and read receipts with one number per member.
Key concepts
- Persistent connections
- Channel subscriptions
- Per-channel sequence
- Idempotent send
- Gap detection
- Keyset pagination
- Read positions
- Presence heartbeats
- Hybrid fan-out
Functional requirements
- Send a message to a channel or a direct message
- Receive new messages in real time on every open device
- Scroll back through a channel's full history
- See unread counts per channel and which members have read a message
- See who is online and who is typing
- Get a push notification for a direct message or a mention while offline
Non-functional requirements
- Messages reach online members in under 300 ms at p99 within a region (a target we chose)
- All members see a channel's messages in the same order
- A message acknowledged to the sender is never lost
- After reconnecting, a client has every message it missed, with no duplicates
- A history page returns in under 200 ms at p99 at any depth (a target we chose)
Interview questions
- How do you guarantee everyone sees messages in the same order?
- A client was offline for 20 minutes. How does it catch up?
- How do you avoid duplicate messages when a client retries?
- How do unread counts and read receipts work at scale?
- How does history paging stay fast deep into a channel?
- How does presence scale to millions of users?
- What changes for a channel with 50,000 members?
- How is this different from an end-to-end encrypted messenger?
Sign up free to read the full topic
More System Design topics
Start free on Cariara · Coding problems · System design studio