Free full guide

Facebook Messenger

Design Facebook Messenger — a real-time chat system delivering messages with low latency, ordering guarantees, and multi-device sync at massive scale.

00

Practice checkpoints

The interview rhythm stays compact, so the page can spend attention on the actual design decisions.

  1. 01
    Clarify scope
  2. 02
    Requirements + scale
  3. 03
    API + data model
  4. 04
    Draw architecture
  5. 05
    Deep dive
  6. 06
    Trade-off decision
01

Requirements that shape the design

Do not only state requirements. Ask for them. Each card pairs the design constraint with a clarification question you can say out loud before drawing the architecture.

Functional requirements

01Just 1:1 chat, or groups too — and how big can a group get?

Users send and receive messages in 1:1 and group chats — groups capped around 100 participants, which keeps fan-out per message bounded.

02What happens to messages sent while I am offline?

Offline messages are delivered on reconnect from a per-user inbox, kept up to 30 days — the server is a relay with a buffer, not a permanent archive.

03One phone per user, or every device in sync?

Users can attach media, and every device a user owns stays in sync — each device tracks its own delivery state.

04Read receipts and typing indicators - in scope?

Receipts yes: they ride the same per-device delivery machinery as messages. Typing indicators are ephemeral presence - best effort, never stored.

05Can users delete a sent message for everyone?

Delete-for-everyone is a tombstone event that propagates exactly like a message; clients that already rendered it replace it in place. Edits stay out of scope.

06Someone joins or leaves a group mid-conversation - what do they see?

Membership changes are ordered events in the chat: joiners receive from the join point onward, leavers stop receiving at the leave event - never partial history.

Out of scopeAudio and video calling · Business messaging and chatbots · Registration and profile management

Non-functional requirements

01How fast must a message reach someone who is online?

Under 500 ms end to end — chat feels instant or it feels broken.

02Can a message ever silently vanish?

No — deliverability is guaranteed: the message is durably written before any delivery attempt, so a dropped connection delays it, never loses it.

03What scale are we designing for?

Hundreds of millions actively messaging; roughly 46K messages per second sent, ~100K writes per second once group fan-out is counted.

04How long do servers keep message content?

No longer than necessary: a 30-day TTL (time-to-live) on the undelivered inbox, then gone.

05What happens when a chat server dies?

Its users reconnect elsewhere and sync from the inbox — because delivery state lives in storage, not in the server’s memory, no message is lost.

Keep asking — the interview is a conversation

Real interviews probe far more than a tidy list. These are the scope questions that separate candidates who interrogate the problem from those who recite it.

  • Group size cap — hundreds or thousands? Fan-out design hangs on it.
  • Is "delivered to server" or "delivered to device" the ack the sender sees?
  • How many devices per account should stay in sync?
  • Is message history a permanent archive, or a 30-day relay buffer?
  • Is end-to-end encryption in scope? It changes what the server can store.
02

Numbers that force architecture decisions

Treat every estimate as a pressure that justifies a component: cache, queue, partition, replica, worker pool, or fallback path.

01

Message write rate

200M active users × ~20 messages/day4B ÷ 86,400 s ≈ 46K msg/s sent · group fan-out ×2-3 ≈ 100K writes/s

Write-optimized storage (LSM log-structured merge trees / wide-column) for Message + Inbox; fan-out work scales with participants, which is why groups are capped.

02

Connections per gateway

~1M concurrent WebSocket connections per beefy gateway box100M concurrently online ÷ 1M ≈ 100+ gateways

Users hash to gateways (consistent hashing + registry) so message routing can find the right box.

03

Cross-server delivery

Sender on gateway A, recipient on gateway Bpublish to recipient’s user channel → only B (subscribed) forwards

Pub/sub partitioned BY USER ID keeps each gateway subscribed only to its own users — partitioning by chat would make busy groups hot.

04

Why durable-write-first

Pub/sub is at-most-once: a dropped subscriber loses the publishwrite Inbox + Message BEFORE publish → worst case = late, never lost

The inbox turns every delivery failure into a reconnect sync instead of a support ticket.

05

Offline inbox size

30-day TTL, ~1KB per message referenceeven 1,000 undelivered msgs ≈ 1 MB per dormant user

TTL keeps the backstop bounded; long-dormant devices resync history from the Message store instead.

Decision example

The numbers

A hundred thousand writes a second, a hundred million people online at once, and a promise: under half a second, and nothing ever silently lost.

My choice

I would keep gateways stateless: a gateway only holds sockets and forwards — every message is durably written to the Message store and each recipient’s Inbox BEFORE any push. Cross-server delivery rides pub/sub partitioned by user ID, so each gateway subscribes only to its own connected users. Heartbeats every 10-30 seconds carry the latest sequence number, so a client that missed anything detects the gap and pulls it. Order is server receipt time — fast beats perfectly ordered in chat.

Avoid

What I would NOT do: keep undelivered messages in gateway memory — one crash and they are gone, which breaks the core promise. I would not partition pub/sub by chat ID — one busy group turns into a hot partition; partition by user instead. And I would not add sharding layers before measuring the actual per-partition message rate — premature sharding adds failure modes, not capacity.

Change if

If end-to-end encryption becomes in scope, the server degrades to a blind router of ciphertext: inbox and multi-device sync must move to per-device message copies and client-held keys.

03

Architecture path

Draw the write path and the read path as separate lanes — they carry different traffic and justify different components.

Facebook Messenger serviceSend path — durable first, then fan outSender ClientGatewayMessage ServiceMessage + InboxStorePub/Sub → GatewaysReconnect path — drain the inboxClient (reconnect)GatewayInbox(undelivered)Message StoreClient syncedPub/Sub (per user)route to gatewaysConnectionRegistrywho is connected wherePush NotificationServiceoffline devicesservicestorequeue / logexternalasync

Durable write first, delivery second. Gateways are stateless socket-holders; the registry knows who is connected where, and offline devices get a push instead of a socket frame.

The sender’s ack fires after the durable write; pub/sub then reaches every gateway holding a recipient device. A missed publish is safe — the inbox already has it.

On reconnect the client drains its inbox and compares sequence numbers; anything missed in transit is pulled, then real-time delivery resumes.

04

API and data model

Before optimizing, make the contract inspectable: endpoints, entities, ownership, retries, and state.

WSsendMessage { chat_id, body, attachments[] }

res{ message_id, status } — ack after durable write

The ack means "stored", not "delivered" — durability first, delivery second.

WSnewMessage → client { chat_id, sender, body }

resclient replies RECEIVED

Pushed over the persistent connection to every online device of every participant.

POST/attachments

req{ body: presigned upload }

res200 { attachment_id, url }

Media goes to blob storage via presigned URL; messages carry only the opaque reference.

WSheartbeat every 10-30 s (piggybacks last sequence)

resclient compares and syncs gaps

Heartbeats detect dead connections AND double as the gap-detection channel.

Core entities

Chat

chat_id (PK) · participants (≤100) · name

Message

message_id (PK) · chat_id · sender_id · body · attachments · server_ts

Ordered and displayed by server receipt timestamp — users would rather see messages fast than in perfect send order.

Inbox

user_id (PK) · message_id · ttl_30d

The durability backstop: written BEFORE any push attempt, drained on reconnect.

Client

user_id (PK) · client_id · last_seen

One user, several devices (~3 cap) — delivery is tracked per client, not per user.

05

Deep dive directions

Pick one lane for the final third of the interview. Each lane gives you the topic, the interviewer question it should answer, and the failure mode to avoid.

01

FocusA hundred million open sockets

AskHow do hundreds of millions of users hold persistent connections, and how does a message find the one gateway holding its recipient?

AvoidBroadcasting every message to every gateway — subscribe gateways only to their own connected users.

02

FocusThe recipient is offline

AskWhere does the message wait, for how long, and what happens the moment they reconnect?

AvoidRelying on pub/sub for durability — it is at-most-once; the inbox write must come first.

03

FocusTwo phones, one account

AskA user reads a message on their laptop. What does their phone need to know, and how is per-device state tracked?

AvoidTracking delivery per user instead of per client — the second device silently misses messages.

04

FocusMessages arrive out of order

AskTwo messages race through different gateways. What order does the recipient see, and why is that acceptable?

AvoidBlocking delivery to enforce global order — users prefer fast over perfectly sequenced.

05

FocusA gateway dies mid-conversation

AskTen thousand users drop at once. What do they lose, and how fast are they whole again?

AvoidAny design where gateway memory is the only copy of an undelivered message.

Ready to practice?

Talk through Facebook Messenger out loud and get AI scoring on the explanation.

Practice this with AI →