Free preview

Media, Evaluation, and Trade-offs

In one line: the media path is a clean example of keeping bulk payloads off a tier tuned for something else — and the evaluation claims encryption is satisfied in a design where it appears nowhere.

The asset service

While WebSocket servers handle text, they are too lightweight for heavy media payloads. The asset service handles sending and receiving media files.

  1. The device compresses and encrypts the media file.
  2. The file is sent to the asset service and stored in blob storage. The service assigns a unique ID and returns it to the sender. It also hashes files to prevent duplication.
  3. The asset service sends the media ID to the receiver via the message service. The receiver uses this ID to download the content.
  4. If content receives high traffic, the asset service loads it onto a CDN.

A separate path because the size ratio is a million to one

Lesson 4 gave the numbers: a text message is 100 bytes; media limits are 16 MB and documents 100 MB.

Text message:    100 bytes
Document:  100,000,000 bytes    -> 1,000,000x

Pushing that through the WebSocket tier would be catastrophic, and the reason is specific to how that tier is built. Lesson 3 explained that 10 million connections per server requires tuning socket buffers down to a few kilobytes for mostly-idle connections. A 100 MB transfer through such a socket would either fail or force buffer sizes that destroy the connection density the whole design depends on.

So media gets a separate service with a separate resource profile, and the messaging path carries only an ID:

upload file -> get ID -> send ID as a message -> receiver downloads by ID

Fan out references, not values — the rule every chapter in this module has reached, applied here to protect a connection tier tuned for tiny sockets.

The CDN promotion on high traffic is the same instinct one level further: a forwarded viral video is requested many times, and serving it from an edge keeps it off the origin entirely.

The dedup claim contradicts the encrypt-on-device claim, in the same list

Step 1 says the device encrypts the file. Step 2 says the service hashes files to prevent duplication.

Lesson 7 worked this through: identical files encrypted with different keys produce different ciphertexts, which hash differently, so deduplication finds nothing.

These two sentences are three lines apart and cannot both be true as stated. The resolutions are convergent encryption — derive the key from the content hash, which restores dedup and leaks whether a known file exists — or accepting that dedup only works for unencrypted content.

Worth raising because it is concrete, checkable, and demonstrates the general point: deduplication requires recognizing identical content, and encryption is designed to prevent exactly that.

Media bytes never traverse the chat servers. A presigned URL is a time-limited, single-object credential, so the client uploads straight to the blob store while the chat tier keeps only a reference. Routing photos and videos through the connection tier would make every chat server a bandwidth bottleneck and force it to scale on media volume rather than connection count.

Presence and last seen

Last seen looks trivial and is a write-amplification trap. Updating a timestamp on every heartbeat means a sustained write per user per interval across the entire user base — enormous traffic to record something almost nobody reads.

The efficient shape is to record only disconnect events and answer the question in two parts: ask the connection tier whether the user is currently connected, and fall back to the stored disconnect timestamp if not. Online status is derivable from state the system already holds.

Requirements compliance

RequirementApproaches
Low latencyGeographically distributed WebSocket servers with local caching · Redis over MySQL · CDNs for media
ConsistencyA FIFO messaging queue for strict ordering · the Sequencer for causality · Mnesia queues messages for sequential delivery on reconnect
AvailabilitySufficient WebSocket servers and replication · load balancer re-establishes sessions on a healthy server · Mnesia primary-secondary replication
SecurityEnd-to-end encryption secures chat data
Scalability~10 million connections per server through performance engineering · horizontal scaling

The security row is one sentence for a property the design never builds

Security: "End-to-end encryption secures chat data against unauthorized access."

That is the entire treatment. And Lesson 7 showed it is not a decoration — E2E determines what the server is allowed to handle, and the design has the server reading, publishing, fanning out, and deduplicating message content.

What an honest row would have to say:

ClaimWhat the design actually does
Server cannot read messagesMessage service stores and filters them by user and message ID
Group messages are encryptedOne message published to Kafka and delivered to all — impossible under E2E
Media is encryptedEncrypted on device — and then deduplicated by hash, which cannot work
History syncs across devicesServer deletes on delivery, so there is nothing to sync

Four contradictions, each between the security claim and a specific design decision made elsewhere in the same chapter.

This is a stronger version of a pattern this module has seen repeatedly — a requirement asserted in the evaluation that the design does not deliver. Yelp claimed consistency from fault tolerance; Instagram claimed it from data integrity. Here the claim is security, and the gap is larger because cryptography constrains architecture rather than describing it.

A property that changes what components are allowed to do cannot be satisfied by naming it in a compliance table.

The consistency row is genuinely good, and it names a real mechanism

Credit where due: "a FIFO messaging queue ensures strict ordering. To handle causality, the Sequencer assigns IDs with appropriate inference mechanisms."

That is precise and correct, and it connects to unique ID generation properly. Ordering within a conversation is exactly what messages need — the requirement's own justification is that "the meaning of the conversation could change" — and monotonic IDs deliver it without global coordination.

It also correctly notes that offline users get sequential delivery on reconnect from Mnesia, so a user returning after a week receives their backlog in order rather than in arrival order.

This is one of the better consistency rows in the module — it names the specific guarantee (ordering), the scope (per conversation), and the mechanism (sequence IDs), rather than asserting "consistent."

The trade-offs

Choosing consistency over availability is the unconventional answer, and I would argue against it

According to the CAP theorem, a system facing network partitions must choose. Since message ordering is essential in this design, we prioritize consistency.

The reasoning about ordering is right and the conclusion does not follow.

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 — the Sequencer mechanism the consistency row just invoked — give you ordering with no cross-partition coordination at all. The recipient reorders on arrival.

A messaging app that becomes unavailable has failed at its purpose. Users judge "the app won't send" far more harshly than "these two messages arrived out of order for a moment." And in practice a message queued on the device and delivered late is barely noticed.

Real messengers choose availability. Messages queue locally and deliver when connectivity returns; the app keeps working through partitions. That is the observable behaviour and it is the opposite of what this evaluation claims.

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

The honest framing is AP with per-conversation ordering — available under partition, with ordering restored by sequence IDs rather than by coordination.

The latency-versus-security trade-off is real and correctly identified

Real-time messaging requires low latency, but transmitting without encryption introduces security risks. The system prioritizes security despite the computational overhead. This overhead is most noticeable when handling multimedia — encrypting large files on the sender's device and decrypting on the receiver's consumes CPU and increases latency.

This is right, and the observation that it hits media hardest is the useful part.

Encrypting 100 bytes of text is imperceptible. Encrypting a 100 MB document on a phone is seconds of CPU and battery — and it happens before the upload even starts, so it is latency the user experiences as the app being slow.

It also explains a design detail: Lesson 8's media flow says the device "compresses and encrypts." Compress first, because compressing ciphertext is useless — encrypted data has no exploitable structure. Order matters: compress, then encrypt.

The cost of encryption scales with payload size, so a system with a million-to-one size ratio between message types feels it in exactly one place.

Key takeaway

Media gets a separate service because the size ratio is a million to one, and the WebSocket tier's socket buffers are tuned down to a few kilobytes to achieve 10 million connections — so bulk payloads would destroy the property the design depends on. The dedup and encrypt-on-device claims contradict each other three lines apart. The evaluation's security row is one sentence for a property that contradicts four separate design decisions — reading messages, group fan-out, media dedup, and multi-device history — because cryptography constrains architecture rather than describing it. Its consistency row is genuinely good, naming guarantee, scope, and mechanism. But choosing consistency over availability is the wrong call: per-conversation ordering comes free from sequence numbers, so unavailability buys nothing.

Next: the whole design under interview conditions.

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