Mock design: chat system
We'll cover the following
Prompt: 1:1 and group chat, 500M daily active users, groups up to 1,000 members, media, end-to-end encrypted, global with EU and India data residency. Answers when asked: online delivery under 500 ms p99, no loss after the ack, same order for everyone, server keeps messages up to 30 days, no backdoor.
Requirements: how to split them
| Functional (what users do) | Non-functional (how well, with a number) |
|---|---|
| Send and receive 1:1 and group messages | Under 500 ms online, p99 |
| Send media | No loss after the ack |
| Sent, delivered and read status | Same order for everyone in a conversation |
| Catch up after being offline | 30-day retention, regional residency, end-to-end encryption |
Numbers
| Item | Value |
|---|---|
| Messages | 500M users x 10 per day = 5B per day |
| QPS | 5B / ~10^5 seconds = ~50K/s (58K exact). Peak 2-3x, so ~150K/s |
| Text volume | 5B x 100 B = 500 GB per day, more with ciphertext and metadata |
| Media | 10% images x 2 MB: 5x10^8 x 2x10^6 B = 10^15 B = about 1 PB per day raw |
| Connections | DAU is not concurrent. Peak 30-50% = ~200M persistent connections |
| Gateways | ~200K connections per box = ~1,000 boxes (1,200-1,500 with redundancy) |
Flow
Sequence between Alice phone, a gateway, the conversation shard, the push service and Bob phone. Alice sends an encrypted message to the gateway, which forwards it to the conversation shard. The shard assigns the next sequence number, replicates it to a majority and acks, so Alice sees one tick. Bob is offline, so the shard asks the push service for a content-free wake-up. Bob phone wakes, connects and sends its cursor 41. The shard replays message 42, Bob acks and Alice sees two ticks.
- Send and save
- Alice phone → Gateway
send(ciphertext, client_msg_id) - Gateway → Conversation shardforward to the owner of this conversation
- Conversation shardAssign
seq=42, replicate to a majority - Conversation shard → Alice phoneack: one tick
- Bob is offline
- Conversation shard → APNs / FCMcontent-free wake-up for Bob devices
- APNs / FCM → Bob phonewake the app
- Bob syncs
- Bob phone → Conversation shardconnect with cursor
41 - Conversation shard → Bob phonereplay
seq=42 - Bob phoneDecrypt locally, show notification text
- Bob phone → Conversation shardack
42 - Conversation shard → Alice phonedelivered: two ticks
- Single tick
- The message is stored on a majority of replicas.
- Double tick
- The receiver device has acked, which is the only proof of delivery.
Where the general lessons live
- Keys, groups and media: End-to-end encryption and key management.
- Order, acks, duplicates, cursor replay: Ordering, acks and delivery guarantees.
- Waking a sleeping phone: Protocols, real-time options and pagination.
- The arithmetic traps: Back-of-envelope estimation.
Data model, groups, regions
messageskeyed by conversation id andseq: ciphertext,client_msg_id, sender, type, media reference, 30-day TTL. Stored once per conversation, never once per recipient.device_cursor: per user, device and conversation, the last ackedseq.devices: push token and public key.- A presence registry (for example Redis): user and device to gateway, with a TTL refreshed by heartbeat.
- Group fan-out: one ciphertext, one
seq. Look up each online member gateway, group by gateway and send one batch per gateway. Offline members get a push plus cursor sync. Cap the group size because deliveries multiply. - Regions: each user has a home region (EU and India stay local), GeoDNS sends them to the nearest gateway, and a conversation owner lives in one region. Replicate synchronously across zones and asynchronously across regions, and say what the async gap does to the recovery point.
Where this mock lost points
- Reversed the key roles in end-to-end encryption.
- Timestamps for ordering and a blanket "availability over consistency".
- Stored a message only when the recipient looked offline.
- Put message text in the push payload, which breaks the encryption requirement.
- QPS off by 1000x, assumed 95% concurrency, forgot media.
- No-loss and ordering were missing from the non-functional list.
Summary: say it in the interview
- "What made this problem special? Ordering and no-loss per conversation, end-to-end encryption, and a push that is only a hint."