system-design · intermediate
Design WhatsApp — 1:1 and Group Messaging
Start here
Design WhatsApp (simplified) means:
- Users send text messages 1:1 and in groups
- Online recipients get messages quickly
- Offline recipients receive messages later
- Optional: last-seen, delivery/read receipts, multi-device
What you will learn
- Clarify chat MVP vs voice/video/status.
- Design gateway connections (WebSocket/long poll).
- Route messages via user sessions.
- Store messages for offline and history.
- Fan-out group messages without O(n²) disasters.
- Discuss receipts, order, and multi-device.
Words you need before we begin
| Term | Plain English |
|---|---|
| Connection gateway | Servers holding active WebSocket sessions. |
| Presence | Online/offline (and device) state. |
| Message queue / inbox | Per-user durable pending messages. |
| Fan-out | Deliver one group message to many members. |
| Delivery receipt | Server/device acknowledges receipt. |
| Read receipt | User opened the message. |
| Idempotency key | Client message id to prevent double-send. |
Requirements
Functional MVP
- 1:1 chat
- Group chat (bounded size for MVP, e.g. 256)
- Offline delivery
- Message history pagination
Non-functional
- Low latency for online delivery
- High durability (messages not lost)
- High connection count
Scale assumptions (example)
- 1B users, 100M online peak
- 20 messages/user/day average → large aggregate QPS
- Groups fan-out dominates complexity
High-level design
flowchart LR
U1[User A] --> GW[Connection gateways]
U2[User B] --> GW
GW --> Chat[Chat service]
Chat --> Sess[(Session directory)]
Chat --> Store[(Message store)]
Chat --> Q[Per-user inbox / queue]
GW --> Push[Push notifications]
Step-by-step design
Step 1 — Connections
Mobile keeps WebSocket to a gateway. Gateways are many; a session directory maps userId → gatewayId/connectionId (and device ids).
Step 2 — Send 1:1
- A sends message with clientMsgId.
- Chat service persists message.
- Lookup B’s active sessions.
- If online, push to gateway(s); if offline, leave in inbox and trigger mobile push notification.
- Ack to A (server received).
Step 3 — Offline inbox
When B connects, drain inbox / fetch since cursor. Mark delivered.
Step 4 — Groups
Options:
- Write fan-out: expand members, enqueue to each inbox (simple reads; heavy writes for large groups).
- Read fan-out: store once per group; members pull group stream (lighter writes; more read logic).
Step 5 — Ordering
Per-chat monotonic server timestamps or sequence numbers. Client shows pending until ack. Do not assume global order across chats.
Step 6 — Receipts
Separate events: server-ack, device-delivered, read. Treat as messages/events themselves with care for privacy settings.
Step 7 — Multi-device
Session directory holds multiple devices; fan-out to all devices; sync cursors per device.
Failure modes
| Mode | Impact | Mitigation |
|---|---|---|
| Gateway death | Dropped sockets | Client reconnect; session update |
| Duplicate send | Double messages | clientMsgId uniqueness |
| Group fan-out storm | Latency | Async workers; backpressure |
| Store outage | Loss risk | Multi-AZ DB; queues durable |
| Presence flapping | Wrong online status | Soft state + TTL heartbeats |
Trade-offs
| Choice | Benefit | Cost |
|---|---|---|
| Persist first then deliver | Durability | Slight latency |
| Deliver then persist | Faster feel | Loss risk |
| Large group write fan-out | Simple recipient inbox | CPU/IO cost |
| End-to-end encryption | Privacy | Server cannot read for search/features |
Common mistakes
- One giant WebSocket server.
- No client message ids.
- Ignoring multi-device.
- Perfect global ordering.
- Building full E2E crypto in 45 minutes—mention, do not implement.
Check your understanding
- What does the session directory store?
- How does offline delivery work?
- Why clientMsgId?
- Name two group fan-out strategies.
- What fails when a gateway process dies?
Practice
- Sequence diagram for 1:1 offline recipient.
- Estimate connections for 50M online users.
- Design inbox schema keys.
- Discuss read receipts privacy.
- Role-play interview with timer.
Deeper production notes
Backpressure
Gateways must limit slow consumers; otherwise memory buffers explode.
Push notifications
APNs/FCM integration is a separate unreliable path—dedupe with in-app delivery.
Additional teaching scenarios
Scenario A — 10× peak
Which component saturates first? What is the first mitigation?Scenario B — partial outage
A dependency is down for 30 minutes. What do users still get, and what is degraded?Scenario C — interview wrap
Summarize the design in five sentences: requirements, MVP, scale lever, failure mode, trade-off.Revision summary
- Chat = connections + durable messages + routing.
- Session directory finds online devices.
- Persist for reliability; fan-out groups carefully.
- Idempotency and reconnect are mandatory.
Glossary
| Term | Definition |
|---|---|
| Session directory | Mapping from user/device to live connection. |
| Inbox | Durable per-user message backlog. |
| Fan-out | Delivering one message to many recipients. |
Abbreviations and terminology
- WS — WebSocket
- E2E — End-to-end encryption
- FCM/APNs — Mobile push providers
What to learn next
Extra teaching notes
When you apply this lesson, write the user-visible success metric first, then the failure mode you fear most. Design the smallest mechanism that protects that metric under partial failure. Prefer explicit timeouts, idempotency, and ownership over adding more infrastructure boxes.
In interviews or design reviews, narrate assumptions, request paths, and trade-offs out loud. A correct-enough design with clear failure handling beats a buzzword diagram without numbers. Revisit the worked example and restate it for a different domain to prove you own the ideas, not the template wording.
Extra teaching notes
When you apply this lesson, write the user-visible success metric first, then the failure mode you fear most. Design the smallest mechanism that protects that metric under partial failure. Prefer explicit timeouts, idempotency, and ownership over adding more infrastructure boxes.
In interviews or design reviews, narrate assumptions, request paths, and trade-offs out loud. A correct-enough design with clear failure handling beats a buzzword diagram without numbers. Revisit the worked example and restate it for a different domain to prove you own the ideas, not the template wording.
Extra teaching notes
When you apply this lesson, write the user-visible success metric first, then the failure mode you fear most. Design the smallest mechanism that protects that metric under partial failure. Prefer explicit timeouts, idempotency, and ownership over adding more infrastructure boxes.
In interviews or design reviews, narrate assumptions, request paths, and trade-offs out loud. A correct-enough design with clear failure handling beats a buzzword diagram without numbers. Revisit the worked example and restate it for a different domain to prove you own the ideas, not the template wording.
Extra teaching notes
When you apply this lesson, write the user-visible success metric first, then the failure mode you fear most. Design the smallest mechanism that protects that metric under partial failure. Prefer explicit timeouts, idempotency, and ownership over adding more infrastructure boxes.
In interviews or design reviews, narrate assumptions, request paths, and trade-offs out loud. A correct-enough design with clear failure handling beats a buzzword diagram without numbers. Revisit the worked example and restate it for a different domain to prove you own the ideas, not the template wording.
Extra teaching notes
When you apply this lesson, write the user-visible success metric first, then the failure mode you fear most. Design the smallest mechanism that protects that metric under partial failure. Prefer explicit timeouts, idempotency, and ownership over adding more infrastructure boxes.
In interviews or design reviews, narrate assumptions, request paths, and trade-offs out loud. A correct-enough design with clear failure handling beats a buzzword diagram without numbers. Revisit the worked example and restate it for a different domain to prove you own the ideas, not the template wording.
Interview and production field guide for this topic
Use this section as deliberate practice, not filler. Rewrite the worked example for a second domain you know well—fintech, education, logistics, or media. Keep the same skeleton: requirements, estimates, high-level diagram, request path, data model, scale lever, failure modes, and trade-offs. If you cannot fill every section without copying buzzwords, you do not yet own the design.
Numbers to force yourself to state
Always speak order-of-magnitude figures: peak QPS, storage growth per day, fan-out factor, connection counts, or queue depth. Wrong numbers that are explicit beat silent hand-waving. Correct the numbers when the interviewer or teammate challenges them; that is collaboration, not failure.
Failure minute
Set a timer for sixty seconds and list only failures: timeouts, duplicates, hot keys, dependency outages, bad deploys, and data corruption paths. For each, name detection and first mitigation. Designs that only describe the happy path are incomplete for production and weak in interviews.
Ownership and operability
Name the dashboard, the alert, the runbook section, and the team that pages. If any are blank, the system will train you during an incident. Prefer progressive delivery: canaries, flags, and rollback notes written before the change lands.
Consistency and retries
State whether the design assumes at-least-once delivery, whether handlers are idempotent, and where unique constraints live. Retries without idempotency are how double charges, double messages, and duplicate fan-out jobs appear. Timeouts without bounds are how thread pools die.
What good looks like in a review
A strong design review or interview answer clarifies scope, makes assumptions audible, draws a minimal path, deepens one or two bottlenecks, and closes with trade-offs and evolution. Use that bar on design-whatsapp round 0 every time you revisit it.
Interview and production field guide for this topic
Use this section as deliberate practice, not filler. Rewrite the worked example for a second domain you know well—fintech, education, logistics, or media. Keep the same skeleton: requirements, estimates, high-level diagram, request path, data model, scale lever, failure modes, and trade-offs. If you cannot fill every section without copying buzzwords, you do not yet own the design.
Numbers to force yourself to state
Always speak order-of-magnitude figures: peak QPS, storage growth per day, fan-out factor, connection counts, or queue depth. Wrong numbers that are explicit beat silent hand-waving. Correct the numbers when the interviewer or teammate challenges them; that is collaboration, not failure.
Failure minute
Set a timer for sixty seconds and list only failures: timeouts, duplicates, hot keys, dependency outages, bad deploys, and data corruption paths. For each, name detection and first mitigation. Designs that only describe the happy path are incomplete for production and weak in interviews.
Ownership and operability
Name the dashboard, the alert, the runbook section, and the team that pages. If any are blank, the system will train you during an incident. Prefer progressive delivery: canaries, flags, and rollback notes written before the change lands.
Consistency and retries
State whether the design assumes at-least-once delivery, whether handlers are idempotent, and where unique constraints live. Retries without idempotency are how double charges, double messages, and duplicate fan-out jobs appear. Timeouts without bounds are how thread pools die.
What good looks like in a review
A strong design review or interview answer clarifies scope, makes assumptions audible, draws a minimal path, deepens one or two bottlenecks, and closes with trade-offs and evolution. Use that bar on design-whatsapp round 1 every time you revisit it.
FAQ from first-time learners
Q: Kafka for every message?
A: Possible for fan-out pipelines; also discuss simpler queues—justify.
Q: SQL for messages?
A: Possible with partitioning by chatId; many designs use wide-column/log stores—justify access patterns.
Q: Exactly-once chat?
A: Aim for at-least-once + dedupe ids.
Track: Distributed Systems
Previous: Design Uber — Matching Riders and Drivers
Next: Design YouTube — Upload, Process, and Stream Video
By Shubham Jain