All questions
#11Messaging & Real-timeHard

Design a Chat App like WhatsApp or Messenger

Deliver one-to-one and group messages in real time, even to offline users.

Meta logo
Microsoft logo
Amazon logo
Uber logo

Asked at Meta, Microsoft and 3 more

3 min read·9 sections

A chat app delivers messages between people in real time: one-to-one, in groups, across phones and laptops, and to people who are offline right now. WhatsApp, Messenger and Slack all solve the same core problems: persistent connections, message routing, ordering and delivery guarantees.

Requirements#

Functional

  • One-to-one and group chats (up to a few hundred members).
  • Messages arrive in real time when the recipient is online.
  • Offline users receive messages when they reconnect, plus a push notification.
  • Sent, delivered and read receipts; online presence.

Non-functional

  • Delivery latency under 200 ms when both users are online.
  • Messages are never lost and appear in the same order for everyone.
  • Hundreds of millions of concurrent connections.

Connections#

HTTP polling wastes battery and adds delay. Clients keep a WebSocket (or MQTT) connection open to a chat server, so either side can send at any time.

Alice's phone
Load balancer
Chat server 1WebSockets
Bob's laptop
Load balancer
Chat server 7WebSockets
Chat server 1
Session registryuser → server
Chat server 1
Message bus
Chat server 7
Chat server 1
Message storeCassandra
Each user is connected to some chat server; a session registry knows which

Sending a message#

  1. Alice's app sends the message with a client-generated ID over her socket to chat server 1.
  2. Server 1 assigns a sequence number within the conversation and writes it to the message store.
  3. It acknowledges to Alice (one tick: sent).
  4. It looks up Bob in the session registry, finds server 7, and forwards the message over the message bus.
  5. Server 7 pushes it to Bob's socket. Bob's app acknowledges, which flows back as "delivered" (two ticks).
  6. If Bob is offline, the message waits in storage and a push notification goes out.

Storing messages#

Chat is write-heavy and read by conversation, newest first. A wide-column store like Cassandra or HBase fits:

text
partition key:  conversation_id
clustering key: message_seq (descending)
columns:        sender_id, body, created_at, client_msg_id

Partitioning by conversation keeps each chat's history on one partition, so loading the latest 50 messages is one sequential read.

Ordering and duplicates#

  • Ordering: wall clocks differ across devices, so don't sort by client time. Assign a per-conversation sequence number on the server (for example, a counter per conversation in Redis, or the conversation's partition leader).
  • Duplicates: networks retry. The client message ID makes the write idempotent: a repeated send with the same ID is acknowledged but not stored twice.

Group chats#

For small groups, the server fans out the message to each member's connection or offline queue. For very large channels, store one copy and let members pull, as with a social feed.

Offline sync and multiple devices#

Each device remembers the last sequence number it has seen per conversation. On reconnect it asks "give me everything after seq 1042", which also handles a phone and a laptop being in sync.

Presence#

Clients send a heartbeat every 30 seconds or so; a user is online if their last heartbeat is recent. Broadcast presence changes only to the user's contacts who are currently online, and batch them to avoid storms when a chat server restarts.

End-to-end encryption#

With E2EE (the Signal protocol), the server only routes ciphertext. That shapes the design: search, link previews and spam filtering must happen on the device.

Finished this walkthrough?

Mark it as read to track your progress in the list.