Free preview

Requirements

In one line: one non-functional requirement here contradicts a design decision made three lessons later, and another is claimed everywhere and specified nowhere.

Functional requirements

RequirementDetail
ConversationSupport one-on-one and group conversations
AcknowledgmentProvide message delivery status — sent, delivered, and read
SharingEnable sharing of media files — images, videos, audio
Chat storagePersist messages for offline users until they are successfully delivered
Push notificationsNotify offline users of new messages when they reconnect

Acknowledgement is a three-state machine, and each state is a different guarantee

"Sent, delivered, and read" — the familiar one tick, two ticks, two blue ticks. Worth taking seriously, because each state is a claim about a different party and requires a different message to travel:

StateMeansConfirmed by
SentThe server has the messageThe chat server, to the sender
DeliveredThe recipient's device has itThe recipient's client, via the server
ReadThe recipient's app displayed itThe recipient's client, via the server

So a single message send produces at least three round trips of acknowledgement traffic, each travelling back through the server to the original sender.

That has a real consequence the chapter's estimate ignores. Lesson 1 computed 1.16 million messages per second; if each generates three acknowledgement events, the system's actual event rate is closer to 4 million per second. Acknowledgements are messages too.

Two more observations worth having.

"Delivered" is a device-level fact, not a person-level one. With multiple devices, delivered to which? That interacts badly with the multi-device requirement below.

"Read" is a privacy disclosure, which is why it is toggleable in real products. It tells the sender something about the recipient's behaviour — the only acknowledgement that reveals a human action rather than a system event.

'Persist until successfully delivered' makes storage a queue, not an archive

Read the storage requirement precisely: "Persist messages for offline users until they are successfully delivered."

That is a queue, not a database. The message exists on the server only during the window between send and delivery, and Lesson 6 confirms the design deletes it afterwards.

Compare every other chapter in this module: tweets, photos, videos, and posts were all stored permanently and served repeatedly. Here the server's copy is transient by design.

Two consequences.

Storage is bounded by undelivered volume, not by total volume. Lesson 3's 300 TB figure assumes 30 days of retention for the undelivered tail — the vast majority of messages occupy the server for seconds.

The server is a relay, not a repository. That is a privacy posture as much as an engineering one: a server that does not retain messages cannot be compelled to produce them.

When storage exists only to bridge a delivery gap, size it by the gap, not by the traffic.

Non-functional requirements

RequirementDetail
Low latencyDeliver messages with minimal delay
ConsistencyDeliver messages in order and ensure chat history is consistent across all user devices
AvailabilityPrioritize high availability, though trade-offs may be made to ensure consistency
SecurityEnd-to-end encryption so only communicating parties can access message content
ScalabilitySupport an increasing number of users and daily messages

'Chat history consistent across all devices' contradicts the storage policy

Put these two statements side by side:

Requirement: "ensure chat history is consistent across all user devices."

Design (Lesson 6): "Once delivered, the message is deleted from the database."

If the server deletes a message the moment it reaches one device, a second device can never fetch it. The history the requirement demands does not exist anywhere the second device can reach.

That is not a small gap — it is why multi-device support in end-to-end encrypted messengers is genuinely hard, and it took real products years to ship. The available resolutions are all expensive:

Deliver to every registered device before deleting. Now "delivered" means delivered to all devices, and a device that is off for a week holds the message on the server for a week. The queue's depth is set by the least-available device.

Encrypted device-to-device sync. The primary device transfers history to a new one directly. Works, and requires both online simultaneously.

Server-side encrypted backup. The server stores ciphertext it cannot read, keyed by something the user controls. Preserves privacy, and reintroduces the storage the design was avoiding.

None is discussed. When a requirement demands state and a design deletes it, one of them has to change — and saying which is a stronger answer than noticing the conflict.

End-to-end encryption is stated here and designed nowhere

"Implement end-to-end encryption so only communicating parties can access message content."

Take that literally and it constrains the entire architecture, because it means the server cannot read what it routes. Consequences that ripple through every later lesson:

No server-side search. The server holds ciphertext; searching chat history must happen on the device.

No server-side content moderation or spam filtering. You cannot classify what you cannot read — which is why encrypted messengers rely on metadata and reporting instead.

Group messaging becomes structurally different. Lesson 7 covers this in full: the design fans one message out to many recipients through Kafka, and under E2E there is no single ciphertext all members can decrypt.

Multi-device requires key management, which is the previous callout's problem.

Media deduplication breaks. Lesson 8's asset service "hashes files to prevent duplication." Two users sending the same photo, each encrypted with different keys, produce different ciphertexts — so the hashes differ and dedup finds nothing.

That last one is a concrete, checkable contradiction between two things the chapter states, and it is worth having ready.

A cryptographic requirement is not a feature you add at the end; it determines what the server is allowed to be. Stating it and then designing a server that reads, fans out, and deduplicates message content is designing a different system.

The availability requirement hedges, and the evaluation resolves it the unconventional way

"Prioritize high availability, though trade-offs may be made to ensure consistency."

And Lesson 9's evaluation makes the choice explicit: "the system prioritizes consistency over availability during a network partition," because "correct message ordering is essential — otherwise the meaning of the conversation could change."

The reasoning about ordering is sound and the conclusion is arguable. A messaging app that becomes unavailable during a partition is a messaging app that stops working, and users judge that far more harshly than a briefly out-of-order thread.

Two things worth saying against it:

Ordering is per-conversation, which is a tiny scope. You do not need global consistency to order one two-person thread — sequence numbers assigned by the sender give you ordering without any cross-partition coordination. The Sequencer chapter's monotonic IDs solve this locally.

Real messengers choose availability. Messages queue on the device and deliver late; the app keeps working. That is the observable behaviour, and it is the opposite of what the evaluation claims.

When ordering can be achieved with local sequence numbers, choosing unavailability to protect it is paying for something you could have had free.

Key takeaway

Acknowledgement is a three-state machine where each state is a claim about a different party — so the real event rate is roughly three times the message rate the estimate never computes. Storage is a queue, not an archive — sized by the delivery gap rather than by traffic, and a server that does not retain cannot be compelled to produce. But that directly contradicts "chat history consistent across all devices": if the server deletes on delivery, a second device can never fetch it. And end-to-end encryption is stated and never designed, though it determines what the server is allowed to be — most concretely, it breaks the media deduplication the design later specifies, since identical files encrypted with different keys hash differently.

Next: the estimation, and the rate it never converts.

Enjoying the preview?

Create a free account to unlock the rest of this course, the in-browser judge, and live AI mock interviews.

Sign up free to continue