Messaging & social, an interactive architecture walkthrough

WhatsApp-style chat app: how the architecture works

How a chat system holds millions of persistent connections, routes end-to-end encrypted messages, and falls back to push when users are offline.

This is a learning explainer based on public engineering writing and general design practice. It is simplified, it is not the actual architecture of any company, and it may be inaccurate.

25 components, 29 connections, 13 steps. Updated 27 October 2026.

Interactive diagram

Overview

A chat system holds one long-lived connection per online user, so its connection tier is stateful and needs a registry that says which server each user is on. Messages are encrypted on the sender's device, so servers only route ciphertext: they assign ordered ids, hold each message only until it is delivered, and park it in an inbox with a content-free push when the recipient is offline. Chat history lives on the devices. This is a generic reference design, not WhatsApp's internal architecture.

Trade-offs and what changes at scale

Keeping messages on the server only until delivery keeps storage small and fits end-to-end encryption, but history then lives on the devices, so backups and adding a new device need extra work; server-history apps (Telegram, Messenger) make the opposite choice. Each linked device has its own keys, so a 1:1 message is encrypted and delivered once per device. Group content is encrypted once with the sender's group key (Signal's Sender Keys), and the server fans out the same ciphertext. At scale the stateful tier is the hard part: spread connections across many servers, shard the session registry, and rate-limit reconnects so an outage does not turn into a reconnect storm. Ordering is kept per conversation, not globally, and delivery is at-least-once, so clients de-duplicate by message id, and very large groups need a cap or a different fan-out path.

How it works, step by step

The walkthrough above, as text. Each step lights up the components named under it.

  1. The app opens a persistent WebSocket through the load balancer to one stateful chat server. Long-lived connections are why this tier is stateful and needs a registry.

    Components Chat Servers, Mobile Clients, Load BalancerVia WebSocket

  2. At registration the app sends the phone number to the auth service over HTTPS, which has an SMS provider send a code; once it is verified, the app receives a token. On every connect the client presents that token; sockets without a valid one are dropped.

    Components Auth Service, SMS/OTP ProviderVia verify token

  3. After auth, the chat server records user to server in Redis with a TTL refreshed by heartbeats. This is how anyone finds the user later.

    Components Presence/Session Registry, Chat ServersVia register session

  4. Alice encrypts a 1:1 message on her device, using Bob's public prekeys that she fetched from the key service when the conversation started, so Bob can be offline. Clients upload their prekey bundles at registration and top up the one-time prekeys as they are used. The chat server forwards the opaque ciphertext to the message service, which never needs to read it.

    Components Message Service, Chat Servers, E2E encryption, Key Service, Mobile ClientsVia send message

  5. The message service assigns an ordered per-conversation id and durably stores the ciphertext, then acks Alice (the 'sent' receipt). The server keeps it only until Bob's device acknowledges it; long-term history lives on the devices. Writes are cheap and partitioned by conversation.

    Components Message Store, Message Service, Presence/Session RegistryVia persist

  6. The registry says Bob is on server B, so the message is delivered there and pushed over his socket. Bob's ack produces the 'delivered' receipt back to Alice.

    Components Chat Servers, Message Service, Mobile ClientsVia deliver

  7. If Bob has no session, the message stays in his offline inbox so nothing is lost. The push service asks APNs/FCM to prompt his device to reconnect with a notification that carries no plaintext. Push is best effort and may be delayed or dropped, so the inbox, not the push, is the source of truth. When he reconnects, the inbox (ids pointing into the message store, not a second copy) drains to his chat server.

    Components Offline Inbox, Push Notification Service, APNs / FCMVia enqueue offline

  8. When Bob opens the chat, his client sends a 'read' receipt. It travels the same route back as a small message, so Alice sees the blue ticks.

    Components Message Service, Chat ServersVia send message

  9. For a group message, the message service asks the group service for the members from the relational DB, then fans out one delivery per member, online or offline. Group content is encrypted once with the sender's group key (Signal's Sender Keys); that key was sent to each member device over its pairwise session. The server fans out the same ciphertext without re-encrypting or reading it. 1:1 chats and key distribution stay per device.

    Components Group Service, User & Group DB, Message ServiceVia expand members

  10. Media is encrypted on the device, uploaded to object storage via the media service, and only a reference plus key travels in the chat message. Chat servers stay light.

    Components Media Service, Object Storage, Mobile Clients, Chat ServersVia HTTPS upload

  11. Recipients download the encrypted blob from the CDN, which caches from S3 close to the user, then decrypt locally.

    Components CDN, Object Storage, Mobile ClientsVia download

  12. Online/offline presence comes from the registry: connect and heartbeat refresh it, and expiry marks a user offline. 'Last seen' is written to a durable store when heartbeats stop or on a throttled schedule; a clean disconnect event cannot be relied on because mobile connections usually drop silently, and the expiring registry entry would take the timestamp with it.

    Components Presence/Session Registry, User & Group DBVia register session

  13. Metrics and logs from each service flow to observability for alerting.

    Components ObservabilityVia metrics

Sequence diagram

The same walkthrough as a UML sequence diagram, one lane per layer or group (19 components in all), left to right in the order a request reaches them, numbered by step. A loop on a lane is a step that stays inside that group. Solid arrows are synchronous calls, dashed are asynchronous.

WhatsApp-style chat app: sequence diagram of the walkthroughLoad BalancerConnection TierMobile ClientsIdentityMessagingData LayerMediaObservabilityWebSocket1WSS1verify token2register / verify OTP2send OTP2register session3send message4upload / fetch prekeys4read / write4persist5lookup server5deliver6enqueue offline7notify7push7drain on reconnect7send message8expand members9SQL9HTTPS upload10store blob10download11origin11register session12last seen12metrics13metrics13metrics13metrics13metrics13

Key components

Connection Tierlayer

Stateful gateway servers

  • Chat Servers: hold WebSockets, push frames to users (websocket)
  • Presence/Session Registry: user -> server map with TTL, presence (redis)

Load Balancer

  • Load Balancer: TLS termination, WebSocket upgrade

Mobile Clients

  • Mobile Clients: iOS/Android apps, persistent WebSocket

Identitydomain

  • Auth Service: phone number verification, tokens
  • Key Service: public prekey bundles, uploaded at registration
  • SMS/OTP Provider: sends verification codes

Messagingdomain

  • APNs / FCM: mobile push providers
  • Group Service: membership lookup
  • Message Service: persist, order ids, route, receipts
  • Push Notification Service: wakes offline devices

Data Layerlayer

  • Message Store: held until delivered; time-bucketed, TTL-expired (cassandra)
  • Offline Inbox: pending message ids (not a copy), drained on reconnect (cassandra)
  • Prekey Store: identity keys and one-time prekeys
  • User & Group DB: profiles, last seen, groups (relational)

Mediadomain

  • CDN: edge delivery of media
  • Media Service: upload URLs, encrypted blobs
  • Object Storage: encrypted images and video (s3)

Observability

  • Observability: metrics, logs, tracing

Sources

Public writing this explainer draws on. Read these for what the real systems actually do.

Make it yours

Copy this diagram and its walkthrough into your own workspace, then change anything: swap Postgres for DynamoDB, add a cache, rewrite the narration. Free, and it uses no AI credits.

This is a learning explainer based on public engineering writing and general design practice. It is simplified, it is not the actual architecture of any company, and it may be inaccurate. Real systems differ in the details. Browse the library.