Design a real-time messaging system with delivery receipts, group chat, and end-to-end encryption.
Problem Statement
Design WhatsApp, a global real-time messaging system for one-on-one chats, groups, media sharing, delivery receipts, read receipts, presence, typing indicators, and offline sync. Clients keep long-lived encrypted connections to a connection gateway layer, and servers route ciphertext without being able to read message contents.
At interview scale, assume billions of registered users, more than a billion users online during peak periods, tens of billions of messages per day, and large regional traffic spikes. The crux is not a simple chat API; it is maintaining persistent connections, mapping each online user and device to a gateway, delivering messages at least once with idempotency, preserving per-conversation ordering, and syncing offline devices after reconnect.
The default design should separate the hot online delivery path from durable mailbox storage, group fanout, media transfer, receipts, and presence. End-to-end encryption shapes the entire architecture: application servers store and route encrypted envelopes, while key exchange and message decryption remain on user devices.
Business use case
WhatsApp lets people and businesses communicate instantly across unreliable mobile networks. Users expect messages to be sent, delivered, read, and synced across devices even when either side is briefly offline or moving between networks.
For the business, messaging reliability drives user trust and daily engagement. The platform also supports high-value surfaces such as business messaging, customer support, media sharing, communities, and notifications while preserving privacy through end-to-end encryption.
Functional Requirements
Maintain long-lived client connections for online users across mobile, desktop, and web clients.
Send and receive one-on-one encrypted messages with delivery acknowledgements.
Support group messaging with membership management and fanout to all recipients.
Persist encrypted messages for offline users and sync missed messages on reconnect.
Expose sent, delivered, and read receipts per conversation and per device where appropriate.
Support presence, last-seen, online status, and typing indicators with graceful degradation.
Support encrypted media upload and download through object storage using message metadata pointers.
Provide idempotent retries so clients can resend safely after network timeouts.
Non-Functional Requirements
Latency
For online recipients in the same broad region, target under 200ms p99 from accepted send to gateway delivery. The sender acknowledgement should return in under 150ms p99 after durable enqueue. Offline sync can be slower, but initial reconnect should begin returning missed messages within one to two seconds.
Availability
Messaging must remain available during cache, receipt, presence, analytics, or media metadata degradation. A practical target is 99.99 percent or higher for sending and receiving text messages, with typing indicators and read receipts treated as best-effort features.
Scalability
The system must support billions of registered users, more than a billion concurrent connections, millions of message sends per second at peak, and even higher recipient-delivery events after group fanout. Connection gateways, queues, stores, and workers must all scale horizontally.
Durability
After the server acknowledges a send, the encrypted message envelope must not be lost. Store it in a replicated message log or mailbox before acknowledgement, retain it until recipient devices have synced or the retention window expires, and keep enough metadata to recover from worker retries.
Ordering
Users expect messages inside a conversation to appear in a stable order. Provide per-conversation sequence numbers or per-sender ordered streams, and make clients handle duplicates and small reordering windows during retries and multi-region failover.
Consistency and idempotency
Delivery is at-least-once, not exactly-once. Clients include a stable client message id and servers store an idempotency record so duplicate sends, worker retries, and reconnect sync do not create duplicate visible messages.
Privacy
Servers should only see encrypted envelopes, routing metadata, timestamps, and coarse delivery state. Message bodies, media plaintext, and user keys remain on devices. Metadata access should be minimized, audited, and protected with strict controls.
Capacity Estimation
Assumptions
Assume 3B registered users, 1.2B daily active users, 1.0B users concurrently online at peak, 70B user-authored messages per day, and an average recipient fanout of 1.7 after one-on-one and group traffic are blended.
Assume each encrypted text message envelope plus metadata is 1 KB before replication, 5 percent of messages include media, average encrypted media object size is 2 MB, each message produces two receipt events on average, and peak traffic is 4x the daily average. A connection gateway can safely hold 500K concurrent long-lived connections with headroom.
Registered users
3B users
Global account population
Peak concurrent connections
1.0B sockets
Mobile, web, and desktop sessions during peak hours
Gateway fleet size
about 2,600 active gateways
1.0B connections divided by 500K per gateway plus 30 percent headroom
Average send QPS
810K sends per second
70B messages divided by 86,400 seconds
Peak send QPS
3.2M sends per second
4x the average send rate
Average recipient deliveries
1.38M deliveries per second
70B messages times 1.7 recipients divided by 86,400 seconds
Peak recipient deliveries
5.5M deliveries per second
4x the average recipient-delivery rate
Receipt events
140B events per day
Delivered and read receipts, about 1.62M events per second average
Message envelope storage
70 TB raw per day
70B messages times 1 KB before replication and indexes
Media ingest
7 PB raw per day
5 percent of 70B messages times 2 MB average encrypted media object
Calculations
- Sends: 70B messages per day divided by 86,400 seconds is about 810K sends per second on average. With a 4x peak multiplier, plan for about 3.2M sends per second.
- Recipient deliveries: 70B messages times 1.7 average recipients is 119B recipient deliveries per day. 119B divided by 86,400 seconds is about 1.38M deliveries per second on average and about 5.5M at peak.
- Gateways: 1.0B concurrent sockets divided by 500K sockets per gateway is 2,000 gateways. Adding 30 percent headroom gives about 2,600 active gateways before disaster recovery spare capacity.
- Receipts: two receipt events per message gives 140B receipt events per day. 140B divided by 86,400 seconds is about 1.62M events per second on average and about 6.5M at peak.
- Message storage: 70B encrypted envelopes times 1 KB is 70 TB raw per day. With 3x replication and index overhead, reserve roughly 250 TB per day for the hot retention tier before compaction and deletion.
- Media: 5 percent of 70B messages is 3.5B media messages per day. 3.5B times 2 MB is about 7 PB raw media ingest per day, so media must use object storage and CDN-style delivery rather than the message database.
- Session registry writes: every connected device refreshes a lease periodically. If 1.0B sessions refresh every 30 seconds, that is about 33M lease refreshes per second, so refreshes must be batched, sharded, and handled by a specialized presence/session tier.
API Design
/ws/v1/connectUpgrades the client to a long-lived encrypted WebSocket or TCP-like session. The gateway authenticates the device, registers a session lease, and returns a resume cursor for missed messages.
Request
GET /ws/v1/connect?deviceId=device_7&resumeCursor=conv_42:88421 Authorization: Bearer access_token X-Client-Capabilities: e2ee,media,multidevice
Response
HTTP/1.1 101 Switching Protocols
Connection: Upgrade
Upgrade: websocket
{
"connectionId": "conn_9af",
"gatewayId": "gw_us_east_318",
"leaseExpiresAt": "2026-07-26T07:45:00Z",
"syncCursor": "global_884210"
}
101— Connection upgraded401— Invalid or expired authentication token409— Device session conflict requires reconnect429— Connection rate limit exceeded
/api/v1/messagesSends an encrypted message envelope to a one-on-one conversation or group. The server validates membership, assigns ordering metadata, persists the envelope, and enqueues per-recipient delivery records.
Request
{
"clientMessageId": "cmsg_01J4",
"conversationId": "conv_42",
"senderDeviceId": "device_7",
"ciphertext": "base64_encrypted_payload",
"mediaId": "media_abc",
"clientCreatedAt": "2026-07-26T07:10:00Z"
}
Response
{
"messageId": "msg_905",
"conversationId": "conv_42",
"serverSequence": 88422,
"serverAcceptedAt": "2026-07-26T07:10:00Z",
"deliveryState": "queued"
}
202— Accepted and durably queued400— Malformed encrypted envelope or unsupported message type401— Authentication required403— Sender is not a conversation member409— Duplicate client message id returned existing message result429— Sender or conversation rate limited
/api/v1/conversations/{conversationId}/receiptsRecords delivered or read state for one or more messages. Receipts are small, high-volume, and eventually consistent; they should not block message delivery.
Request
{
"deviceId": "device_7",
"receiptType": "read",
"upToServerSequence": 88422,
"observedAt": "2026-07-26T07:10:05Z"
}
Response
{
"conversationId": "conv_42",
"receiptType": "read",
"acknowledgedUpTo": 88422
}
200— Receipt accepted400— Invalid receipt cursor401— Authentication required403— Device is not authorized for the conversation
/api/v1/syncFetches missed encrypted messages, receipts, and conversation metadata after a reconnect or when a secondary device catches up. The cursor is per device so multiple devices can advance independently.
Request
GET /api/v1/sync?deviceId=device_7&afterCursor=global_884000&limit=500 Authorization: Bearer access_token
Response
{
"nextCursor": "global_884500",
"hasMore": true,
"messages": [
{
"messageId": "msg_905",
"conversationId": "conv_42",
"serverSequence": 88422,
"ciphertext": "base64_encrypted_payload"
}
]
}
200— Sync page returned400— Cursor is invalid or too old401— Authentication required410— Requested cursor is outside retention and full resync is required
/api/v1/media/upload-urlReturns a short-lived signed upload URL for encrypted media. The client encrypts media locally, uploads it to object storage, and then sends a normal message containing the media pointer and encrypted media key material.
Request
{
"conversationId": "conv_42",
"contentType": "image/jpeg",
"encryptedSizeBytes": 2048000,
"sha256": "client_computed_hash"
}
Response
{
"mediaId": "media_abc",
"uploadUrl": "https://objects.example.com/upload/media_abc?signature=signed",
"downloadUrl": "https://media.example.com/media_abc?signature=signed",
"expiresAt": "2026-07-26T07:25:00Z"
}
201— Signed upload URL created400— Unsupported media type or size401— Authentication required413— Media object too large429— Upload quota exceeded
The public API is only part of the story. Most real traffic flows over the persistent gateway protocol after connection establishment. Send, ack, receipt, typing, and presence frames can use compact binary envelopes over the long-lived connection, while REST endpoints are useful for sync, media URL issuance, and management operations.
Every send request must carry a client-generated idempotency key. The server should return the same message id and sequence for duplicate retries instead of creating another visible message.
Database Design
The database stores encrypted message envelopes and routing metadata, not plaintext. The hot model is a combination of append-only conversation logs, per-recipient mailboxes, group membership tables, and an ephemeral session registry.
Conversation ordering is represented by a server sequence scoped to a conversation. Delivery is represented by mailbox rows scoped to recipient user and device, which lets offline sync read missed work without scanning global message logs.
| conversation_id | uuid | Primary key for one-on-one or group conversation |
| conversation_type | varchar(20) | Direct, group, community, or broadcast-like product type |
| created_at | timestamp | Creation time |
| created_by_user_id | uuid | User that created the group or direct conversation |
| latest_sequence | bigint | Monotonic sequence assigned within this conversation |
| membership_version | bigint | Changes when members join, leave, or rotate keys |
| conversation_id | uuid | Partition key paired with user_id |
| user_id | uuid | Conversation participant |
| role | varchar(20) | Member, admin, owner, or removed |
| joined_at | timestamp | Membership start time |
| left_at | timestamp nullable | Membership end time for access checks |
| device_key_version | bigint | Helps clients know when sender keys or sessions changed |
| conversation_id | uuid | Partition key for the ordered conversation log |
| server_sequence | bigint | Sort key within the conversation |
| message_id | uuid | Globally unique stable message id |
| client_message_id | varchar(128) | Idempotency key unique per sender device |
| sender_user_id | uuid | Author account |
| sender_device_id | uuid | Author device for multi-device sync |
| ciphertext_ref | text | Encrypted envelope or pointer to encrypted blob storage |
| media_id | uuid nullable | Optional encrypted media pointer |
| server_accepted_at | timestamp | Ordering and retention timestamp |
| expires_at | timestamp nullable | Retention or disappearing-message deadline |
| user_id | uuid | Recipient partition key |
| device_id | uuid | Recipient device, or logical all-devices mailbox |
| mailbox_sequence | bigint | Per-recipient ordered sync cursor |
| conversation_id | uuid | Conversation containing the message |
| message_id | uuid | Message to deliver or sync |
| delivery_state | varchar(20) | Queued, delivered, read, expired, or failed |
| visible_after | timestamp | Supports delayed retry and backoff |
| ttl_expires_at | timestamp | Mailbox retention deadline |
| user_id | uuid | Online user id |
| device_id | uuid | Online device id |
| gateway_id | varchar(64) | Connection server currently holding the socket |
| connection_id | varchar(128) | Opaque session handle on the gateway |
| region | varchar(32) | Serving region for routing |
| lease_expires_at | timestamp | Short lease refreshed by gateway heartbeat |
| capabilities | json | Client protocol and device features |
Indexes
- messages.conversation_id, server_sequence is the primary read path for ordered conversation history.
- messages.sender_device_id, client_message_id must be unique enough to implement idempotent send retries.
- user_mailboxes.user_id, device_id, mailbox_sequence supports reconnect sync without scanning conversations.
- conversation_members.conversation_id, user_id supports membership checks and group fanout.
- connection_sessions.user_id, device_id maps an online recipient to the current gateway and connection id.
Relationships
A conversation has many members and many ordered messages. Each accepted message creates one or more mailbox records, one per recipient device or per recipient logical inbox depending on the multi-device model. Connection sessions are short-lived leases, not the source of truth for message durability.
Receipts can be stored as compact per-user cursors such as delivered_up_to and read_up_to per conversation instead of one row per message when semantics allow. This reduces receipt storage from per-message state to per-conversation cursors.
NoSQL alternatives
Use a log-structured or wide-column store such as Cassandra, HBase, Bigtable, or DynamoDB for conversation logs and mailboxes. Partition conversation logs by conversation id plus sequence buckets to avoid oversized partitions in very large groups. Partition mailboxes by user id and device id because reconnect sync is recipient-oriented.
Use Redis, Aerospike, or a custom sharded in-memory store for the session registry because connection leases are extremely hot and short-lived. Use object storage for encrypted media and a separate streaming system such as Kafka, Pulsar, or Kinesis for fanout, receipts, and analytics.
High-Level Architecture
Clients hold long-lived connections to gateways. Gateways register short leases in the session registry so message routing can find the server that currently owns each recipient device. Durable message state lives in logs and mailboxes, while presence, typing, receipts, and media are adjacent systems with weaker coupling.
The architecture has two hot paths. The online path routes a ciphertext envelope from sender device to connection gateway, through the message service, into durable storage and recipient mailboxes, then back to a recipient gateway if the session registry says the recipient is online. The offline path leaves the encrypted envelope in a recipient mailbox until reconnect sync reads it by cursor.
The connection gateway layer is intentionally stateful for sockets but stateless for correctness. If a gateway dies, clients reconnect through the load balancer, create a new session registry lease, and resume from the last acknowledged mailbox cursor. The message store and mailbox queue remain the correctness boundary.
End-to-end encryption means servers route opaque payloads and store ciphertext. Media is encrypted on the client and uploaded to object storage through signed URLs; messages carry only media pointers and encrypted keys for recipient devices.
Request Flow
- 1
Client connects and registers presence
The client authenticates and establishes a long-lived connection to a nearby gateway. The gateway creates a short session lease mapping user id and device id to gateway id, connection id, region, and protocol capabilities. Presence is updated as best effort.
- 2
Sender encrypts locally
Before sending, the client encrypts the message using recipient device sessions from the Signal protocol style key exchange. For a group, the client uses group sender-key material or per-recipient encrypted key envelopes. The server receives only ciphertext and routing metadata.
- 3
Gateway forwards send to message service
The sender gateway validates authentication freshness, attaches connection metadata, and forwards the encrypted envelope plus client message id to the message service. If the client retries after a timeout, the same client message id is reused.
- 4
Message service checks membership and idempotency
The service verifies that the sender belongs to the conversation, checks whether the client message id was already accepted, and either returns the existing message id or assigns a new message id and per-conversation sequence number.
- 5
Envelope is persisted before acknowledgement
The encrypted envelope is written to the conversation log and recipient mailbox records are created or enqueued. Only after this durable boundary does the service acknowledge the sender with a sent state and server sequence.
- 6
Online recipients are routed through gateways
Delivery workers read recipient mailbox work, query the session registry, and push the message to the gateway that owns each online device. The gateway sends the frame over the existing socket and records a delivery acknowledgement when the client confirms receipt.
- 7
Offline recipients sync later
If no active session exists, the mailbox entry remains durable. On reconnect, the device calls sync with its last cursor and receives missed messages, receipts, and membership changes in mailbox order. The client deduplicates by message id.
- 8
Receipts and presence propagate asynchronously
Delivered and read receipts are written as compact cursors and fanned out to interested participants. Typing and online indicators are ephemeral; they can be dropped during overload because they are not correctness-critical.
- 9
Media follows a separate object-store path
For media, the sender encrypts the file locally, uploads it through a signed URL, and sends a normal message containing a media id and encrypted metadata. Recipients download the object directly and decrypt locally.
Core Components
Connection Gateway
Terminates long-lived client connections and pushes frames to online devices.
Gateways manage WebSocket or long-lived TCP sessions, heartbeats, reconnect tokens, backpressure, per-connection rate limits, and protocol framing. They keep socket state in memory but write short leases to the session registry so routing services can find online devices.
Session Registry
Maps user and device sessions to the gateway currently holding the connection.
The registry stores short-lived leases keyed by user id and device id. It must handle extreme write rates from heartbeats and reconnects, tolerate stale entries through lease expiry, and provide fast lookups for delivery workers.
Message Service
Validates sends, assigns ordering metadata, persists encrypted envelopes, and creates delivery work.
This service is the correctness boundary for send acceptance. It checks membership, enforces idempotency, allocates per-conversation sequence numbers, stores ciphertext, and enqueues recipient mailbox records before acknowledging the sender.
Mailbox Queue
Buffers per-recipient delivery work for online push and offline sync.
A mailbox is the durable inbox for each recipient device or logical user. It supports at-least-once delivery, cursor-based reconnect sync, delayed retries, expiration, and deduplication by message id.
Group Service
Owns group membership, admin actions, and membership versions used during fanout.
The group service answers who should receive a group message at a specific membership version. It also coordinates key-rotation metadata so clients know when group encryption state changes after joins, leaves, and device changes.
Fanout Workers
Expand group messages and retry delivery without blocking sender acknowledgement.
Workers consume group fanout tasks, create per-recipient mailbox work, shard large groups, retry transient failures, and protect the message service from doing unbounded fanout synchronously.
Presence Service
Provides online, last-seen, and typing signals as best-effort metadata.
Presence is high-volume and low-criticality. The service should aggregate heartbeat state, apply privacy settings, expire typing indicators quickly, and degrade before it harms core message delivery.
Media Object Store
Stores encrypted media blobs outside the messaging database.
Clients upload encrypted media through signed URLs and include media pointers in messages. Object storage and CDN-like delivery handle large bytes, while the message service stores only small metadata and encrypted keys.
Deep Dive
Persistent connections and session routing
A WhatsApp-like system is built around long-lived connections, not polling. Each online device has a socket to one gateway. The gateway periodically refreshes a lease in a session registry containing user id, device id, gateway id, connection id, region, and expiration time.
Delivery workers should not broadcast to all gateways. They query the registry for a recipient device and send to the owning gateway. Because registry entries can be stale, gateway delivery must be conditional: if the connection id no longer exists, the worker leaves the mailbox entry for later sync or retries after a fresh lookup.
Heartbeats are the scale hazard. Refreshing 1B sessions every few seconds would overload any ordinary cache. Use longer leases, gateway-level batching, sharded registries, delta heartbeats, and local gateway state. Presence freshness can be approximate; routing correctness comes from durable mailboxes and client acknowledgements.
At-least-once delivery, idempotency, and mailbox design
Exactly-once delivery across mobile networks, retries, queues, and reconnects is not realistic. The server should provide at-least-once delivery and make every stage idempotent. The client sends a stable client message id. The message service stores a mapping from sender device plus client message id to server message id and sequence. If the client retries, it gets the same result.
Each recipient has a mailbox entry referencing the message id and conversation sequence. Delivery workers may retry the same mailbox item many times. Gateways may push duplicates after reconnect races. Clients deduplicate by message id and can acknowledge up to a mailbox cursor.
The sender can see sent after durable enqueue, delivered after a recipient device acknowledges receipt, and read after the recipient opens the conversation or advances a read cursor. These states are monotonic but eventually consistent.
Ordering per conversation
Users expect a conversation to feel ordered even when messages are sent from multiple devices and regions. A common design assigns a monotonically increasing server sequence per conversation at acceptance time. The client displays messages by server sequence, with client timestamp only as secondary metadata.
The challenge is large groups and hot conversations. A single per-conversation sequencer can become hot. For ordinary chats, a leader shard per conversation is simple. For very large groups, use sequence allocation in ranges, conversation partitioning, or accept looser ordering with deterministic merge rules. The interview answer should explicitly state that global ordering across all conversations is unnecessary.
Retries must preserve sequence. If the same client message id is retried, the server returns the original server sequence. If failover occurs before acknowledgement, recovery must decide whether the sequence was committed by checking the idempotency record and message log.
Group messaging fanout
One-on-one messaging creates one recipient delivery per send. Group messaging can create hundreds or thousands. Small and medium groups can use fanout-on-write: expand the recipient set at send time and enqueue one mailbox item per recipient. This gives fast offline sync because each user's mailbox already contains the message.
Very large communities may need hybrid fanout. Store one group message in the conversation log, enqueue for online active members first, and let inactive members pull from the group log on sync. This reduces write amplification but makes read and cursor logic more complex.
Membership version matters. A user who joins after a message should not receive old ciphertext unless history sharing is enabled, and a user who leaves should not receive future messages. Fanout tasks should include the membership version and clients should rotate group encryption keys when membership changes.
Offline sync and multi-device
Offline support is a first-class requirement. When a device reconnects, it should not ask every conversation for missing messages. It should read a recipient mailbox or device sync log using a single cursor. The response contains encrypted messages, receipt updates, membership changes, and tombstones in a bounded page.
Multi-device increases complexity because a user may have phone, web, desktop, and companion devices with independent encryption sessions and cursors. The system can either create mailbox entries per device or maintain a logical user inbox plus device-specific delivery state. Per-device mailboxes are more expensive but make sync correctness clearer.
Retention policies matter. If a device is offline longer than the mailbox retention window, the server should return a cursor expired response and require a fuller resync from conversation logs or a client backup, depending on product policy and encryption constraints.
End-to-end encryption and media
End-to-end encryption changes what servers can do. Servers cannot inspect message text for search, spam decisions, previews, or smart replies unless clients provide separate privacy-preserving signals. The server stores ciphertext, sender and recipient identifiers, timestamps, envelope size, and delivery state.
The Signal protocol family uses device identity keys, prekeys, sessions, and ratcheting so each device can decrypt only messages intended for it. For groups, clients can use sender keys or per-recipient key wrapping to avoid encrypting the full payload separately for every member.
Media should never flow through the message database. The client encrypts the media, uploads it to object storage, and sends a message containing a media id, content hash, size, and encrypted media key material. Recipients fetch the object and decrypt locally.
Scaling
Prototype: single region and simple chat service
Start with one regional WebSocket gateway fleet, a message service, a relational or document store for conversations, and a simple Redis-backed online registry. Support one-on-one messaging, basic offline storage, and idempotent client message ids before adding large groups.
Growth: sharded gateways and durable mailboxes
Shard gateways by region and connection id, move messages and mailboxes into a partitioned wide-column or log store, and introduce queue-backed delivery workers. Separate presence and receipts from the core send path so they can fail independently.
Large scale: group fanout and multi-device
Add group membership versioning, asynchronous fanout workers, per-device sync cursors, media object storage, and hot conversation protection. Split high-cardinality receipt streams from message envelope storage and compact receipts into per-conversation cursors.
Global scale: billions of users and regional isolation
Use geo-routing to connect clients to nearby gateways, keep conversations homed to a region or shard group for ordering, replicate metadata across regions, and provide disaster recovery with explicit tradeoffs around ordering and duplicate delivery. Keep online routing regional whenever possible to avoid cross-region hops on every message.
Extreme scale: communities and business messaging
Use hybrid fanout for massive groups, capacity isolation for business senders, adaptive rate limits, spam scoring based on metadata and reports, and specialized stores for media, receipts, search metadata allowed by clients, and analytics. Preserve the core invariant: acknowledged messages are durably recoverable.
Bottlenecks & Optimizations
Session registry write amplification
Do not write every heartbeat as an independent global cache update. Batch leases at the gateway, refresh only when a lease is near expiry, shard by user id and device id, and treat presence freshness as approximate. Use durable mailboxes as the source of truth when registry state is stale.
Group fanout write explosion
Fanout small groups on write, but shard large groups into batches and process asynchronously. For very large communities, use hybrid fanout where inactive users pull from a group log during sync. Apply per-group rate limits and protect fanout workers from a single hot group.
Hot conversations and sequencing contention
A single sequence allocator can bottleneck on active groups. Assign conversations to sequencer shards, allocate sequence ranges, use partitioned logs for large groups, and avoid global ordering. Monitor per-conversation queue depth and p99 sequence allocation latency.
Receipt event volume
Delivered and read receipts can exceed message volume. Store compact monotonic cursors such as delivered up to and read up to, batch updates, coalesce repeated reads, and drop low-value receipt fanout during overload before dropping messages.
Media overwhelming message infrastructure
Keep media out of gateways and message databases. Use signed URLs, client-side encryption, object storage multipart upload, virus scanning where product policy allows, CDN-style download acceleration, and separate quotas for media senders.
Offline reconnect storms
After an outage or app update, millions of clients may reconnect and sync at once. Use randomized backoff, resume tokens, paginated sync, per-user limits, gateway admission control, and priority for small recent mailbox pages.
Failure Handling
Connection gateway crashes
All sockets on that gateway disconnect. Clients reconnect through the load balancer, old session leases expire quickly, and new leases are written. Messages acknowledged before the crash are still in durable mailboxes, so reconnect sync replays missed envelopes.
Session registry outage or stale entries
Continue accepting sends by writing message logs and mailboxes. Online push may degrade, but recipients can recover through sync. Delivery workers should treat registry misses as offline state and stale hits as retryable failures, not message loss.
Message store partition unavailable
If the durable write path is unavailable for a conversation shard, do not acknowledge new sends for that shard. Queue briefly only if durability is preserved elsewhere. Fail over to a replica or home region, then use idempotency records to avoid duplicate accepted messages.
Fanout worker backlog
Sender acknowledgement can still happen after durable enqueue, but delivered receipts will lag. Scale workers by shard, prioritize one-on-one and small groups, expose delayed delivery metrics, and apply sender or group rate limits if backlog threatens retention.
Regional outage
Route new connections to healthy regions. Conversations homed in the failed region may become read-only or temporarily unavailable unless replicated write ownership can move safely. Prefer duplicate-tolerant recovery over pretending exactly-once delivery survived failover.
Object storage or media CDN degraded
Text messaging should continue. Media upload URL creation can fail or return retryable errors, while existing media downloads can use alternate replicas. Message envelopes with media pointers should clearly show pending or failed media state on clients.
Security
End-to-end encryption
Message plaintext and media plaintext stay on devices. Servers store and route ciphertext, manage prekey distribution, enforce device identity changes, and never require plaintext to provide delivery. Clients should warn users when safety numbers or device identities change.
Authentication and device trust
Every connection and send frame is authenticated with a user and device identity. Device enrollment, session revocation, token refresh, and suspicious login detection are critical because a stolen session can send valid encrypted messages.
Spam and abuse controls
Because servers cannot inspect plaintext, abuse detection relies on metadata, rate patterns, user reports, block lists, business sender reputation, link safety signals, and client-side protections. Controls must avoid weakening encryption guarantees.
Metadata minimization
Routing metadata is sensitive even without message content. Limit retention of IPs, device identifiers, contact graph signals, and precise presence. Use access controls, audit logs, aggregation, and privacy settings for last-seen and read receipts.
Media safety
Media is encrypted before upload, so server-side scanning may be limited by privacy policy. Enforce size limits, signed URLs, short token lifetimes, abuse reporting flows, quarantine mechanisms for reported media, and safe client rendering.
Transport security and replay protection
Use TLS for client-to-gateway transport, signed protocol frames, nonce or sequence checks where applicable, and idempotency windows to prevent replayed sends from creating duplicate messages or forged receipts.
Tradeoffs
Pros
- +Persistent connections give low-latency delivery without client polling.
- +Durable per-recipient mailboxes make offline sync and retry semantics explicit.
- +At-least-once delivery with idempotent clients is realistic for mobile networks.
- +End-to-end encryption protects message content even from server compromise.
- +Separating media, presence, receipts, and messages lets non-critical features degrade independently.
Cons
- −Maintaining a billion long-lived connections requires a large stateful gateway fleet.
- −End-to-end encryption prevents server-side plaintext search, moderation, and rich previews unless clients cooperate.
- −Group fanout creates heavy write amplification and hot-conversation risks.
- −Per-device multi-device sync significantly increases mailbox and receipt complexity.
- −Strong per-conversation ordering can conflict with multi-region availability during failover.
Alternatives
Alternative one is client polling against a REST API. It is simpler, but it wastes battery and bandwidth and cannot meet real-time latency at global scale.
Alternative two is a pure pub-sub system with no durable mailbox. It works for online-only chat, but offline users lose messages and reconnect sync becomes unreliable.
Alternative three is fanout-on-read for all groups. It reduces write amplification, but reconnect sync becomes expensive because each user must scan group logs and compute visibility on demand.
Alternative four is server-visible plaintext to support search, spam filtering, and previews. It simplifies product features but violates the privacy requirement and is not acceptable for a WhatsApp-like design.
When not to use this design
Do not use this design for low-volume enterprise chat where compliance requires server-side retention, eDiscovery, and plaintext indexing; a Slack-like system may be more appropriate. Also do not use it for public broadcast feeds where follower fanout, ranking, and timeline storage dominate rather than private encrypted delivery.
Follow-up Questions
Why not use HTTP polling instead of persistent connections?
Polling is easier but inefficient for mobile clients and adds latency between polls. Persistent connections let the server push messages, receipts, and typing indicators immediately while also supporting heartbeats and backpressure. The tradeoff is stateful gateway operation at very large scale.
How do you guarantee exactly-once delivery?
You generally do not. The practical design is at-least-once delivery with idempotency. The sender uses a stable client message id, the server maps it to one message id and sequence, delivery workers retry mailbox records, and clients deduplicate by message id.
How is ordering handled in group chats?
Assign a server sequence number scoped to the conversation or to a sequence shard for very large groups. Clients display by that sequence. The system should not attempt global ordering across all conversations. For hot groups, use range allocation or relaxed deterministic ordering to reduce sequencer contention.
What happens when the recipient is offline?
The message remains in the recipient mailbox with a cursor. The sender can see sent after durable enqueue, but delivered waits until a recipient device reconnects, syncs, and acknowledges receipt. Retention policy determines how long offline messages are kept.
How does end-to-end encryption affect backend design?
Servers cannot inspect or transform message bodies. Backend services route ciphertext, store encrypted envelopes, manage metadata, and distribute public prekeys. Features that need content, such as search or previews, must be implemented on device or with explicit privacy-preserving client support.
How do you scale to very large groups?
Use fanout-on-write for normal groups because it makes recipient sync simple. For massive groups or communities, shard fanout, prioritize active online users, and let inactive users pull from a group log. Include membership versioning so visibility and encryption state are correct.
How do you handle reconnect storms after an outage?
Gateways enforce admission control and ask clients to use exponential backoff with jitter. Sync is paginated by mailbox cursor, recent small pages are prioritized, and old large syncs are throttled so the system can restore online delivery first.
Company Variations
Meta
Meta interviewers are likely to push on the true WhatsApp crux: billions of persistent connections, Signal protocol constraints, group fanout, presence privacy, abuse without plaintext inspection, and multi-region failure behavior. Be ready to explain why durable mailboxes are the correctness boundary.
Amazon
Amazon may frame this around operational excellence, sharded queues, DynamoDB or Kinesis-style primitives, noisy-tenant isolation for business messaging, and clear failure modes. Expect pressure on capacity math, backpressure, retry storms, and cost of media storage.
Microsoft
Microsoft may compare the design with Teams-style enterprise messaging. Discuss device identity, compliance tradeoffs, Azure Front Door-like routing, tenant and region isolation, auditability of metadata access, and how end-to-end encryption limits server-side search.
Google tends to probe distributed systems fundamentals: long-lived connection balancing, tail latency, per-conversation ordering, hot shard mitigation, global replication, and SRE metrics for delivery freshness and reconnect storms.
LinkedIn may connect messaging to professional identity, spam prevention, invitations, and notification fanout. Emphasize abuse controls, rate limits, inbox sync, and the difference between private encrypted chat and feed or notification systems.
Interview Tips
Lead with the connection-oriented nature of the system. Draw the gateway and session registry first, then the durable message log and recipient mailbox, then group fanout, receipts, presence, and media. Keep repeating the key invariant: once the sender sees accepted, the encrypted envelope is durable and recoverable even if online push fails.
When discussing tradeoffs, separate correctness-critical features from best-effort features. Message persistence, idempotency, and sync are critical. Typing indicators, last-seen freshness, and analytics can lag or drop during overload.
What interviewers expect
- ✓Start with requirements for one-on-one, groups, offline sync, receipts, presence, media, and encryption.
- ✓Draw client to load balancer to connection gateway to message service to mailbox and store.
- ✓Explain session registry leases and why stale entries are safe with mailbox recovery.
- ✓Use at-least-once delivery with idempotent message ids and client deduplication.
- ✓Quantify billions of sockets, millions of sends per second, receipt volume, and media storage.
- ✓Discuss group fanout, per-conversation ordering, multi-device sync, and failure handling.
Common mistakes
- !Designing only REST polling and ignoring persistent connection gateways.
- !Claiming exactly-once delivery instead of at-least-once with idempotency.
- !Forgetting offline mailboxes and reconnect sync cursors.
- !Sending media through the message database or gateways.
- !Ignoring end-to-end encryption and accidentally relying on server plaintext access.
- !Treating typing indicators and read receipts as equally critical as message durability.
Red flags
- ×No session registry mapping online users to gateway servers.
- ×No capacity math for concurrent sockets, fanout, receipts, or media.
- ×No per-conversation ordering story.
- ×No duplicate handling for client retries and worker retries.
- ×No separation between durable message storage and ephemeral presence.
- ×No plan for stale gateway leases, reconnect storms, or offline retention.
Revision Notes
- WhatsApp is a persistent-connection system: online devices hold WebSocket or long-lived TCP sessions to connection gateways.
- The session registry maps user id and device id to gateway id, connection id, region, and lease expiry.
- The registry is an optimization for online push, not the source of truth. Durable mailboxes and message logs provide correctness.
- Delivery is at-least-once. Use client message ids, server message ids, idempotency records, and client deduplication.
- A sender can see sent after durable enqueue, delivered after recipient device acknowledgement, and read after recipient read cursor advances.
- Preserve order per conversation with a server sequence. Do not promise global ordering across all chats.
- One-on-one sends create small fanout. Groups require membership-versioned fanout and may need hybrid fanout for massive communities.
- Offline sync reads a per-user or per-device mailbox cursor and returns encrypted messages, receipts, and metadata changes in pages.
- End-to-end encryption means servers route ciphertext and cannot inspect message bodies. Media is encrypted client-side and stored in object storage.
- Presence, typing, and last-seen are best-effort. They should degrade before message sending and offline sync.
- Capacity hotspots are concurrent sockets, heartbeat leases, recipient fanout, receipt events, media bytes, and reconnect storms.
Flashcards
Quiz
0/7 answered
1.Which component maps an online recipient device to the server holding its socket?
2.What delivery guarantee is most realistic for WhatsApp-style messaging?
3.When should the server acknowledge a send as accepted?
4.Why is a per-recipient mailbox useful?
5.Which feature should degrade first during overload?
6.What is the best storage path for encrypted media files?
7.What does end-to-end encryption prevent the server from doing by default?
Cheat Sheet
Goal: global private messaging with persistent connections, one-on-one and group delivery, receipts, presence, offline sync, encrypted media, and end-to-end encryption.
Scale: 3B registered users, 1B peak concurrent sockets, 70B messages per day, about 810K average sends per second, about 3.2M peak sends per second, and about 5.5M peak recipient deliveries per second after fanout.
Connection layer: clients connect to regional gateways through a global load balancer. Gateways hold sockets and refresh leases in a sharded session registry mapping user and device to gateway and connection id.
Send path: sender encrypts locally, gateway forwards ciphertext, message service checks membership and idempotency, assigns per-conversation sequence, persists the encrypted envelope, creates mailbox work, and acknowledges sent.
Delivery path: workers read mailbox items, look up recipient sessions, push to online gateways, and retain items for offline sync if no valid session exists. Clients acknowledge and deduplicate by message id.
Ordering: order within a conversation using server sequence numbers. Avoid global ordering. For hot groups, shard fanout and protect the sequencer.
Offline sync: each user or device has a cursor over mailbox work. Reconnect sync returns missed messages, receipts, membership changes, and tombstones in pages.
Groups: fanout-on-write for normal groups. Use membership versions and asynchronous workers. Use hybrid fanout for massive communities.
Receipts and presence: sent is durable enqueue, delivered is device receipt, read is read cursor. Presence, last-seen, and typing are best effort and privacy controlled.
E2EE: servers route ciphertext and manage metadata. Device keys and plaintext stay on clients. Media is encrypted client-side and stored in object storage via signed URLs.
Failure rule: if online push fails, do not lose the message. Let leases expire, reconnect, and replay from durable mailboxes.
References
- DocsThe Double Ratchet Algorithm — Signal
- DocsThe X3DH Key Agreement Protocol — Signal
- BookDesigning Data-Intensive Applications — Martin Kleppmann
- PaperKafka: a Distributed Messaging System for Log Processing — Jay Kreps, Neha Narkhede, and Jun Rao
- DocsRFC 6455 The WebSocket Protocol — IETF