vs Read Receipts
Last seen vs read receipts — same mutual rule, different enforcement point
Both features hide information. But one is suppressed by the client, the other by the server. The reason is where the data originates.
The surface similarity¶
Both features: - Show one user's activity to another - Can be turned off in privacy settings - Enforce the same mutual rule: hide yours, lose others' - Store the setting as a user-level flag
They feel like the same feature. But the enforcement mechanism is fundamentally different.
Read receipts — client suppresses the event¶
Read receipts work by Bob's client sending a read event to the server when Bob opens a chat:
Bob opens chat → Bob's client generates read event → sends over WebSocket → server updates last_read_seq → pushes blue tick to Alice
The read event is generated by the client. The client is the source.
When Bob turns off read receipts, the client simply never generates the event:
Bob opens chat
→ Bob's client checks: read_receipts_on = false
→ Bob's client: do not generate read event
→ Nothing sent over network
→ Server: never knows Bob opened the chat
→ Alice: never sees blue tick
The suppression happens at the origin — before anything is sent. Zero network cost. The server is completely unaware.
Last seen — server suppresses the response¶
Last seen is a timestamp recorded by the server when Bob disconnects. The client doesn't generate it. The WS server writes it to the DB the moment it detects the disconnect:
Bob disconnects → WS server records last_seen[bob] = now()
This happens regardless of Bob's privacy setting. The server always records the timestamp — it has to, because the disconnect event happens server-side and there's no way to "unsee" it.
The privacy enforcement happens later, when Alice requests the timestamp:
Alice opens chat with Bob
→ server fetches last_seen[bob]
→ server checks: does Bob have last_seen hidden?
→ if yes: do not include in response
→ Alice: sees nothing
The data exists on the server. The server chooses whether to reveal it.
Why they can't use the same enforcement point¶
Could read receipts be server-enforced like last seen?
Technically yes — Bob's client sends the read event, server checks the setting and drops it. But this wastes network bandwidth. The client has the setting cached. It knows before sending that the event will be dropped. Sending it anyway is pointless.
Could last seen be client-enforced like read receipts?
No — the disconnect happens on the server. When Bob's phone loses signal, the WS server detects the heartbeat timeout and records the timestamp. Bob's client is unreachable at that moment — it can't suppress anything because it's already gone.
Even if Bob's app could send a "don't record my last seen" message before closing — the ungraceful disconnect (signal loss, battery death) would bypass it entirely. The server has to record the timestamp regardless.
The key difference¶
Read Receipts Last Seen
─────────────────────────────────────────────────────────
Data origin Client (read event) Server (disconnect detection)
Privacy enforcement Client-side Server-side
Enforcement point Before sending Before responding
Network cost Zero (event suppressed) Zero (timestamp withheld in response)
Mutual rule Same Same
Setting location Users table (cached) Users table (cached on client for read receipts check)
Same outcome. Same mutual rule. Different enforcement layer — because the data originates at different layers.
The general principle¶
Enforce privacy as close to the data origin as possible
If the client generates the data → client suppresses it (read receipts). If the server generates the data → server suppresses it (last seen). Never send data you're going to throw away.
Interview framing
"Both use the same mutual rule, but the enforcement point differs. Read receipts are suppressed client-side — the client generates the read event, so it checks the setting before generating it, and zero bytes travel over the network. Last seen is suppressed server-side — the server records the timestamp on disconnect regardless of settings, so the server checks the privacy flag before including it in the response."