Skip to content

Functional Requirements

The system

A real-time messaging system where users can send and receive text messages 1-on-1, view their chat history, and see their most recent conversations at the top. Think WhatsApp — without media, group chats, or read receipts for now.


The three core flows

WhatsApp at its simplest is three things working together.

The first flow is sending a message — a user types something and hits send. That message needs to travel from their device to the recipient's device in real-time. If the recipient is offline, the message needs to wait and be delivered when they come back.

The second flow is chat history — when a user opens a conversation, they need to see all the previous messages between them and the other person, in order, oldest to newest. This is a read path: fetch the message history for a given conversation and display it.

The third flow is the inbox — the home screen of WhatsApp. A list of all the people you've talked to, sorted by who you talked to most recently. The latest message shows as a preview. This seems simple but is actually a tricky read — you need to know the most recent message across all of a user's conversations.


What's in scope

  • 1-on-1 text messaging — send and receive text messages between two users in real-time
  • Chat history — load all previous messages between two users
  • Inbox / recent chats — show conversations sorted by most recent message, with a preview

What's out of scope (and why you deferred it)

Group chats

Group chat is a meaningfully different problem. Sending a message to one person is straightforward — you know exactly who to deliver it to. Sending to a group involves fan-out: one message needs to be delivered to N recipients. At WhatsApp scale with groups of 256 people, a single message send becomes 256 delivery operations. That fan-out design is its own deep dive. Deferring it keeps the core design clean.

Media (images, video, documents)

Text messages are tiny — around 250 bytes each. The moment you add images (average 1-3 MB) or video (tens of MB), your storage and bandwidth estimates change by orders of magnitude. You'd need a separate upload flow, blob storage (S3), thumbnail generation, and progressive loading. All of that is separable from the messaging core. Text only keeps the estimation honest and the design focused.

Read receipts (single tick / double tick / blue tick)

Read receipts are a notification-within-a-notification. When you read a message, the sender's client needs to be updated. This requires a separate event flow back from reader to sender — essentially reverse messaging. It's non-trivial and distracts from the core delivery problem. Defer it, but know it could be added later with a status update event.

Presence (last seen / online indicator)

Presence is a high-frequency write problem. If you update a user's "last seen" timestamp every time they do anything in the app, that's potentially millions of writes per second for 100M DAU. It's also privacy-sensitive. Out of scope for now — but it's worth noting that WhatsApp eventually let users turn it off entirely, which tells you how contentious it became.


Interview framing

The three flows — send/receive, chat history, inbox — are the obvious answer. What makes a strong answer is knowing what you're deferring and why. Group chat changes your fan-out architecture. Media changes your storage and upload design. Read receipts add a reverse event flow. Presence adds a high-frequency write problem. Deferring them is the right call — but you should be able to say why each one is its own problem, not just "out of scope."