SDSystem design
Start learning free

LESSON 95 OF 140 · PRACTICE PROBLEMS

SYSTEM DESIGN · INTERVIEW WALKTHROUGH

Design Facebook Messenger: System Design Interview Practice

The problem

"Design Facebook Messenger." It looks like Design WhatsApp, and most of that design carries over. The difference is that people are signed in on several devices at once: a phone, a laptop, a browser tab at work. Every message, every "Seen" and the whole history must look the same on each, and a laptop that was closed for a week must catch up exactly.

This practice problem reuses the pattern of Design Chat (WhatsApp). The decisions go to what several devices change: how each device catches up, what "Seen" means, what typing costs, and how years of history are searched. Park calls, reactions, stories and payments.

The numbers

From the interviewer, as in Chat: about 1 million messages a second at busy hours. Say everyone is signed in on 3 devices.

what                  worked out                     about
devices per message   Ben's 3 + Ana's other 2        5 (one-to-one)
deliveries            1 million messages × 5         5 million a second
log entries           1 million × 2 members          2 million a second

The sender's own devices are the surprise: Ana's laptop must show what she sent from her phone. Groups multiply it again: a message to 6 people with 3 devices each goes to 17 devices.

Catching up: a numbered log per person

In Chat, a message was marked delivered when the other phone acked it. With several devices that breaks: Ana's phone acks, the message is marked delivered, and her laptop, closed since yesterday, is never sent it. Asking each of her 200 chats for "anything newer" when the laptop opens is no better: 200 reads, nearly all empty, and a chat started while it was closed is missed.

Instead, give each person one numbered log. Every message to or from Ana, and every change to one such as a deletion, gets the next number in her log. Each device keeps a cursor, the last number it has, as in Dropbox, and asks for everything after it:

device   cursor   asks for       gets
phone    1,240    after 1,240    nothing: up to date
laptop   1,204    after 1,204    36 entries, 1,205 to 1,240, in order

The cursors are the delivery state, one per device. Online devices also get each new entry pushed down their WebSocket and move their cursor as they take it. Each message costs one log entry per member: 2 for a one-to-one chat.

"Seen" per person, not per device

Ben reads Ana's "Dinner at 8?" (m205) on his laptop while his phone stays in his pocket. Ana cares whether Ben saw it, not on which screen, so "Seen" appears once any of his devices has read it. Waiting for all of them would mean waiting forever for an old tablet in a drawer, and a Seen per device tells Ana more than Ben may want.

The server keeps one read marker per person per chat: "Ben has read c42 up to m205". It only moves forward, so a device that opens an older message later can't move it back. The marker goes to Ana's devices, which show Seen, and to Ben's phone, which clears its unread badge: one row per member of the chat, not a flag on every message for every device.

Typing: passed on, never stored

A message, a read marker or a deletion must still be known tomorrow, so each is stored and gets a number in every member's log. "Ana is typing…" is useless a few seconds later. The server passes it straight to the devices that have the chat open and drops it: no database, no log. Each device shows the indicator for a few seconds unless a fresh one arrives, so a laptop that dies mid-word doesn't leave "typing…" up for good.

Searching years of history

History is kept forever, partitioned by chat and sorted by message id, as in Tables From Query Patterns: right for "the newest 50 in this chat", useless for a word. Finding "dinner" by reading Ana's 200 chats would read 6 years of messages on every search.

So each saved message is also added to a search index, each word pointing to the messages that contain it, one index per person, filled a moment later off a queue so sending stays fast. A search is one lookup in Ana's index; the price is a group message indexed once per member. One caveat: Meta began making end-to-end encryption the default for personal Messenger chats in late 2023, and then the servers can't read the text, so search has to run on each device. In the interview, say which one you are designing.

Same pattern as Chat (WhatsApp)

The connection layer carries over unchanged: a WebSocket from each online device to a connection server, a session store with one entry per device, a chat service that saves every message before sending it on, and push notifications for devices that are offline. What changed is that a person is no longer one phone, so delivery, receipts and history are kept per device and per person.

Summary

  • Scope: every message on every device, history forever and searchable, Seen and typing.
  • Numbers: 5 devices per one-to-one message, about 5 million deliveries a second.
  • Catching up: a numbered log per person, a cursor per device.
  • Seen: one read marker per person per chat, from any device.
  • Typing: passed on to open chats, never stored.
  • Search: an index per person, fed off a queue.
Keep going with system designInteractive lessons from the building blocks to Twitter, Uber and payments, the way interviews ask. Free to start.
Start learning free