Read Receipts: Problem Statement and Interview Framing
How Read Receipts: Problem Statement and Interview Framing shapes architecture and interviewer follow-ups for Design Read Receipts.
Read Receipts: Problem Statement and Interview Framing
Read receipts sit on the critical path of perceived messaging quality: senders want confidence that content arrived and was seen, while recipients often want control over visibility. Define the product as a metadata side-channel on top of messaging: sent, delivered, and read states with timestamps. WhatsApp uses gray checks then blue checks; Slack shows seen-by in channels; iMessage exposes read timestamps when enabled. The interview tests whether you can model a monotonic per-recipient state machine, fan-out updates to senders, and privacy gates without breaking message delivery.
Mechanism and invariants
Receipt state advances in one direction: sent → delivered → read. A recipient cannot move from read back to delivered. The server enforces this with a rank column or enum ordering in a conditional update. Duplicate client posts with the same idempotency key must not create extra fan-out storms.
For group chats, treat each member as an independent state machine keyed by (message_id, recipient_id). The sender UI rarely needs all N rows in real time—publish an aggregate counter and offer a detail drawer on tap. This cut reduces WebSocket traffic by orders of magnitude in teams channels.
Privacy and product policy
WhatsApp-style mutual consent means disabling read receipts prevents you from seeing others' read states too—implement as a pairwise gate at notification time, not merely UI hiding. Delivered receipts (double gray check) typically remain enabled because they do not reveal attention, only device reachability.
Operations you should mention
Measure receipt_lag_seconds (client emit → sender UI), illegal_transition_rate, privacy_suppressed_count, and group_aggregate_refresh_latency. Alert when consumer lag on receipts.by.conversation exceeds 30s. Run game days for regional broker loss with client replay buffers.
Interview pivot lines
If challenged on cost, explain TTLed cold storage and aggregate fan-out. If challenged on E2E, clarify that ciphertext is untouched—you only process envelope metadata. If asked about Discord skipping receipts, discuss social pressure and meaningless aggregates at thousands of members.
Section 1 deep dive
This section emphasizes Read Receipts in the read-receipts design narrative. Connect every decision to sender trust, recipient privacy, and measurable fan-out cost—avoid hand-waving "we'll use Kafka" without partition keys, idempotency, or backoff policies.
1 public enum ReceiptStatus { SENT, DELIVERED, READ } 2 public record ReceiptEvent(String messageId, String recipientId, ReceiptStatus status, long atEpochMs) {}
1 def receipt_key(message_id: str, recipient_id: str) -> str: 2 return f"{message_id}:{recipient_id}"
1 export type ReceiptStatus = "sent" | "delivered" | "read"; 2 export function canAdvance(current: ReceiptStatus, next: ReceiptStatus): boolean { 3 const order = { sent: 0, delivered: 1, read: 2 } as const; 4 return order[next] >= order[current]; 5 }
Why interviewers care
Read Receipts interviews reward crisp scope, explicit trade-offs, and failure stories—not generic microservice diagrams.
Interview checkpoint
Name one failure story for Read Receipts: Problem Statement and Interview Framing that proves you understand real outages, not happy-path diagrams.
Key Highlights
- •Monotonic sent→delivered→read per recipient
- •Privacy gate before sender visibility
- •Aggregate group updates to limit fan-out
- •Idempotent receipt ingress with CAS writes
Section Rescue Kit
Buzzwords to use:
Safe statements:
- "I will separate delivered acknowledgements from read receipts because they carry different privacy expectations."
- "For groups I will aggregate read counts to keep fan-out bounded."