Review: FB Live Comments
Design comments for a live video room.
Clarify this prompt before choosing components
Ask the highest-impact questions first, agree on priorities, and record the interviewer’s answers. If a detail is unspecified, state an assumption and explain which decision depends on it. The numbers in this worked lesson are exercise assumptions, not company facts.
| Ask the interviewer | Why the answer changes the design |
|---|---|
| Per-stream order or a global order? | A hot stream needs an explicit ordering owner; global order is usually unnecessary. |
| Peak viewers, comments/s and acceptable delivery lag? | Bound fan-out, replay and slow-client buffers. |
| How do moderation and reconnect affect already delivered comments? | Define delete/tombstone updates and gap-resume semantics. |
Use the Interview Playbook for the shared 45-minute sequence and fresher, intermediate, senior and staff evidence. Start with one complete operation. Extend the answer with the failure/recovery traces below, then defend a workload-specific alternative and a measurable rollout. Scope and evidence matter more than a large component list.
FB Live Comments: Understand the building blocks
Choose a mechanism because it satisfies a requirement. These explanations describe the exercise design, not undisclosed implementation choices at the named company.
FB Live Comments: Quick vocabulary
| Term | Meaning and role in this exercise |
|---|---|
| API: Application Programming Interface | The contract for requests, responses and errors between components. An API route does not itself enforce every business invariant. |
| HTTP: Hypertext Transfer Protocol | The request/response protocol used by web APIs and media fetching. Application retries still need safe operation identities. |
FB Live Comments: Server-Sent Events (SSE)
What it means: A server-to-client event stream over HTTP. Client commands still use a separate request path.
Why this problem needs it: Viewers primarily receive low-latency comment events.
How to use it: Give events stable IDs and define retention/replay when reconnecting; bound slow-client buffering.
Example in this design: Receive identified server events while posting comments via an authorized request.
When it fits: Useful for comments, progress or model output when the client primarily receives updates.
Alternative and limits: WebSocket provides bidirectional messaging. SSE event IDs are not a database transaction or a guarantee of unlimited replay.
FB Live Comments: WebSocket
What it means: A protocol for bidirectional messages over a persistent connection after a handshake. It is a transport, not a durable message store.
Why this problem needs it: Bidirectional interactions may justify a different transport.
How to use it: Authenticate the session, route incoming messages to their owner, and bound outgoing buffers. Reconnect using application message IDs and cursors.
Example in this design: Choose it for the declared interaction contract; do not infer durable history from a socket.
When it fits: Useful when both sides send frequent low-latency updates.
Alternative and limits: Polling is simpler at low update rates; Server-Sent Events fit one-way server updates. A new connection does not restore missed messages by itself.
FB Live Comments: Snapshot, retained suffix and recovery cursor
What it means: A snapshot records state at a named revision; the retained suffix contains later changes; a cursor marks a declared consumed position.
Why this problem needs it: Disconnects need a bounded replay cursor and overlap handling.
How to use it: Recover from one consistent snapshot/revision and replay the necessary suffix with stable identities. Reset explicitly when required history expired.
Example in this design: Replay 41–50 and live 49–53 deduplicate by event identity.
When it fits: Useful to bound replay and let disconnected clients catch up.
Alternative and limits: Full replay is simpler for tiny histories. A cursor beyond unapplied events can lose updates; two unrelated reads do not form one consistent snapshot.
FB Live Comments: Durable work queue and backpressure
What it means: A queue separates accepted work from execution. Backpressure limits admission or consumption when downstream capacity is finite.
Why this problem needs it: Slow clients must not cause unbounded broadcast buffering.
How to use it: Persist a stable job identity, consume with bounded concurrency, acknowledge after the required durable transition, and cap retries/backlog according to policy.
Example in this design: Cap a subscriber queue and disconnect/reset according to the agreed loss policy.
When it fits: Useful for asynchronous work that must survive worker failure or absorb a finite burst.
Alternative and limits: A synchronous call is simpler for short bounded work. A queue does not create capacity, strict global ordering or exactly-once external effects.
Interview scope and guarantees
Post comments to a live event, display recent comments with low delay, reconnect without duplicates, and remove moderated content. Ordering is per stream or shard, not necessarily global across the service. Slow consumers must not stall the broadcaster.
Capacity worksheet
Assume one event has 1 million viewers and 1,000 comments/s. Sending every 200-byte comment to every viewer would be 200 GB/s before protocol overhead. That product expectation is often unnecessary; offer a moderated or sampled view, batch updates, and define what each viewer receives.
Concrete API contract
POST /streams/{id}/comments {clientId,text} -> {commentId,sequence}
GET /streams/{id}/comments?after=...
SSE /streams/{id}/events?cursor=...
DELETE /comments/{id} -> moderation eventData model and access paths
comments(stream_id,sequence,comment_id,author_id,text,state)
stream_offsets(stream_id,partition,offset)
moderation(comment_id,version,state)
client_dedup(author_id,client_id,comment_id)Evolve a solution and explain each change
Read the diagram
Append comments / Authenticate the author and append a stream-scoped comment ID. / Per-viewer polling wastes work and does not define replay.; Push bounded streams / Fan out persisted comments over session connections with resume cursors. / Slow viewers can accumulate unbounded buffers.; Handle hot broadcasts / Shard fanout delivery, filter moderation changes, and shed overload predictably. / Delivery shards do not automatically create a global comment order.
Step 1: Append comments
Authenticate the author and append a stream-scoped comment ID. Per-viewer polling wastes work and does not define replay.
Step 2: Push bounded streams
Fan out persisted comments over session connections with resume cursors. Slow viewers can accumulate unbounded buffers.
Step 3: Handle hot broadcasts
Shard fanout delivery, filter moderation changes, and shed overload predictably. Delivery shards do not automatically create a global comment order.
Responsibility overview
Read the diagram
Viewer to Comment API: post or resume; Comment API to Comment log: append stream position; Moderator to Comment API: moderate comment; Comment log to Fanout worker: durable delivery intent; Fanout worker to Session registry: find active sessions; Fanout worker to Viewer: bounded live delivery
Worked end-to-end scenario
A viewer posts c20 and disconnects before the response. Retrying the client comment ID returns the stored comment. Broadcast subscribers receive c20 through fanout workers, but a slow phone fills its buffer. Rather than accumulating unlimited memory, send a resync signal or disconnect according to policy. The phone reconnects with its stream cursor and fetches a bounded persisted range. A moderator removes c20. The system emits a tombstone or removal event; reconnect replay must not resurrect it. A hot stream can use several delivery shards while one ordered ingest partition assigns stream positions.
Why these access paths matter
Persist by broadcast ID and stream position. Deduplicate author/client IDs and index moderation state. Connection registries map broadcast shards to active sessions; they are ephemeral delivery state, not authoritative history. If sampled comments are allowed under overload, state that separately from full replay and make the client aware of gaps.
Build the baseline first
Read the diagram
Comment API → durable append → ordered stream; Fanout service → connection gateway → viewers; Reconnect cursor → retained history → live handoff
- Comment API → durable append → ordered stream.
- Fanout service → connection gateway → viewers.
- Reconnect cursor → retained history → live handoff.
Evolve the design under load
Read the diagram
Stream partitions → regional fanout tree; Gateway batches → bounded client buffers; Moderation event → removal projection → clients
- Stream partitions → regional fanout tree.
- Gateway batches → bounded client buffers.
- Moderation event → removal projection → clients.
Defend the hardest decision
An append log preserves a resumable position. Gateways subscribe once per popular stream and fan out locally, rather than establishing one broker subscription per viewer. A client that cannot keep up receives a bounded backlog or a reset-to-latest instruction. If the system samples comments, the UI must not imply a complete ordered transcript. A cursor should encode the shard positions needed to resume a partitioned stream.
Failure and recovery analysis
After a disconnect, subscribe to the live stream while fetching history with a defined high-water mark, then deduplicate the overlap. Fetching history first and subscribing later creates a gap. A moderation deletion must suppress future replay and update connected clients; removing only the database row leaves already-buffered copies visible.
Security and privacy boundary
Rate-limit authors, escape rendered content, and preserve moderator audit trails without leaking removed text to unauthorized readers.
Interview follow-ups with reasoning
Question: Can SSE replace WebSockets?
Show answer and explanation
Answer: Yes for server-to-browser updates while posting uses HTTP.
Question: How do you handle a viral stream?
Show answer and explanation
Answer: Split fanout work across regions and gateways while protecting the append authority.
Question: What do you measure?
Show answer and explanation
Answer: Publish-to-display lag, slow-client drops, reconnect gaps and moderation propagation delay.
Operate and verify the design
Publish-to-display delay, slow-client drops, replay resets and moderation lag.
Reconnect a viewer during a burst and verify the history/live handoff has no unexplained gap.
A second scenario to test transfer
A room receives 100 comments/s and has 100,000 viewers. At an illustrative 500 bytes per delivered event, raw fanout is 5 GB/s before protocol overhead. The storage write rate is modest compared with delivery bandwidth. A popular-room tier can batch or sample display events under a stated UX policy while preserving accepted comments in history. Adding database replicas alone does not solve socket fanout.
A reconnect cursor is older than retained events. What should the server return?
Show answer and explanation
Answer: An explicit reset/snapshot requirement with a new valid cursor. Silently starting at the newest event would hide a gap. The UI can show a recent window and disclose that earlier live history is unavailable.
Compare alternatives
| Concern | Mechanism | Trade-off |
|---|---|---|
| Hot room | Hierarchical fanout | More routing state |
| Slow device | Bounded buffer + resume | May need snapshot reset |
| Moderation | Removal events + authoritative history | Propagation delay |
| Ordering | Room-scoped cursor | No global ordering promise |
A design-changing exercise
A fanout node crashes after accepting a comment. Is the comment lost?
Show answer and explanation
Answer: Not if acceptance meant durable log insertion. Delivery can be reconstructed from the log and subscriber cursors; memory-only fanout is not enough.
Design workshop: replay-to-live without gaps
Core scope is posting, recent history, live viewing and moderated removal for one broadcast. Ranking every historical comment is excluded. Choose live delivery p95 under one second under admitted load, durable accepted comments and a 30-minute replay window. Popular-room display sampling, if enabled, is disclosed; it does not delete accepted history.
CONNECT /streams/id/comments accepts afterCursor. Events include streamId, sequence, commentId, type, contentVersion and payload. A cursor binds stream and position; a cursor for another stream is rejected. If it precedes retention, return reset_required with a recent snapshot and new cursor. Never silently return only newest events while pretending the suffix is complete.
Subscribe to live output, capture durable high watermark H, fetch (cursor,H], then consume live output after H. Buffer/overlap may repeat events, so deduplicate by stream/sequence. A bounded buffer overflow during handoff aborts and requires another replay. Attaching after a historical query without a watermark can lose the events between those steps.
Read the diagram
Resume after 40; Subscribe with bounded buffer; Read high watermark H=43 and suffix 41..43; Buffered event 43 then 44; Deliver 41,42,43; drop overlap 43; deliver 44; Persist/ack last delivered cursor 44
A room log assigns sequence under one ordered append authority. Fanout delivery is then sharded across gateway groups; delivery-shard IDs are not a room-wide order. A session registry maps room→gateway populations and expiring sessions. Root fanout distributes batches to regional workers, then gateway groups, then bounded per-socket queues. Persisted history stays independent of session presence.
Read the diagram
Assumption / Calculation / Implication; 1,000 comments/s × 1M viewers × 200 bytes / 200 GB/s raw payload / Network hierarchy, not only DB scaling; 100,000 sockets × 8 KiB buffer / 819 MB buffer payload / Connection metadata adds more memory; Batch 20 events over 20 ms / One envelope per batch / Bound latency; reduce protocol overhead; Slow socket exceeds buffer / Reset and recent snapshot / Do not allocate unlimited memory
Sample display at a gateway only under a product contract that labels the stream as selected comments. Preserve ordering among delivered events and carry a cursor over skipped ranges so resume semantics are explicit. Full-history clients query the durable log, not the sampled socket stream. Backpressure can reject new writes with 429 under overload or accept durably and signal delayed delivery; choose the boundary honestly.
Moderation appends a versioned removal event for comment C. Clients apply newer content versions and retain a bounded tombstone so a delayed create cannot resurrect C. Reconnect snapshots exclude removed content. A moderator can race with publication; authorization and policy checks happen at the write authority and renderer. Report moderation propagation lag separately from accepted-comment latency.
Exercise: Live output is subscribed at time T, the historical query returns through 43, and events 43/44 are buffered. What is sent?
Show answer and explanation
Answer: History through 43, then only buffered events strictly after 43. If the buffer overflows, restart from a supported durable cursor rather than skip to the latest event.
Requirement trace and verification
| Requirement | Implementing design block | Verification link |
|---|---|---|
| R1 — Complete the primary user journey within the stated scope. | P01–P04; P09–P10. | V1 — Exercise the successful journey and the excluded/boundary case stated in the scope. |
| R2 — Preserve the problem's authoritative data invariant under concurrency. | P05–P06; P11–P12; DD1. | V2 — Run the race/replay case below and assert the invariant at the durable authority. |
| R3 — Meet the declared scale and API behavior without unbounded work. | P05–P08; P13–P14; relevant overload deep dives. | V3 — Exercise the API errors/retry identity and recompute the workload assumption that drives partition or capacity. |
| R4 — Recover from the named failure without losing or duplicating the user-visible outcome. | P15–P16; deep dives; Operations contract. | V4 — Disconnect mid-stream and reconnect while new comments arrive; verify stable order and documented sampling behavior. |
Operational contract
| Area | Decision and signals |
|---|---|
| SLIs | Publish-to-display lag; replay/live gap resets; moderation lag; slow-client drops; hot-room queue depth. |
| Overload limits | Cap per-stream publish rate, subscriber fanout, replay window, and slow-client buffers. |
| Recovery | Resume from durable sequence/snapshot watermark; reset expired cursors from a consistent snapshot. |
| Access controls | Apply stream membership and moderation policy before fanout; protect private room and author data. |
| Dominant cost | Hot-stream fanout bandwidth and retained replay history. |
Senior-level interviewer follow-ups
Question: A viewer subscribes while the room is receiving comments. How do you avoid a gap?
Show answer and explanation
Answer: Return a high-watermark cursor, subscribe, and replay the overlapping range with deduplication by room sequence. Bound the buffer and fall back to a fresh snapshot if replay exceeds retention.
Question: What does a slow viewer receive when a celebrity room exceeds fanout capacity?
Show answer and explanation
Answer: Apply a documented room policy such as sampling, batching, or dropping low-priority updates while preserving ordering metadata and moderation removals. Bound per-client buffers and expose the degraded mode.
A 60-second design answer
I would persist moderated comments with a room sequence, then fan them through a hot-room distribution tier. Subscribe-and-replay uses a watermark and deduplication to close the live/history race. Slow consumers receive bounded batches or a documented sampled view; moderation removals carry versions. I would measure room skew, replay lag, dropped updates, buffer pressure, and end-to-end freshness.
Related concepts to revisit
Technical references
Kafka processing and external-sink boundaries.
PostgreSQL transaction isolation and concurrent updates.
Join history and live delivery at one watermark
Capture a consistent retained-history boundary 100. Return history through 100 and subscribe/replay from 101 under a protocol that closes the handoff gap. If the live path repeats 100, stable sequence deduplication removes it. Reading history first and only afterward subscribing without replay can lose comments committed in between.
history snapshot: through 100
new comments: 101,102
live/replay start: after 100
duplicate 100: ignore; apply 101,102Read the diagram
history snapshot: through 100; new comments: 101,102; live/replay start: after 100; duplicate 100: ignore; apply 101,102
SSE is a reasonable one-way browser path; user posting remains an authenticated API operation. Routing by stream and distributing scoped events avoids making every server process every comment. A mega-stream may exceed one viewer's useful rate: declare sampling/coalescing or snapshots rather than promising every event to every client. Bound client buffers and reconnect work, and recheck access on resume.
Show answer and explanation
Answer: An expired Last-Event-ID requires resync under retention rules. A socket reconnect succeeding does not prove the missing comments were recovered.
Decision review: FB Live Comments
FB Live Comments: What it is
A live-comment design accepts identified events, fans them out and joins replay to live updates without a silent gap.
FB Live Comments: Why it is needed
Connections fail and clients progress independently; slow consumers can consume unbounded buffers if not controlled.
FB Live Comments: When to use it
Use a retained event/cursor contract when reconnect must recover missed comments; permit snapshot/reset when the cursor exceeds retention.
FB Live Comments: How to use it
Establish the replay/live handoff at a known watermark, apply overlapping event IDs once and enforce current room/moderation policy. Bound per-connection buffers and define disconnect, drop or resync behavior.
FB Live Comments: Compare an alternative
Polling can satisfy a looser freshness target with less connection state. Push reduces update latency but adds routing, buffer and reconnect work.
FB Live Comments: Worked decision exercise
The following inputs and policies are original exercise assumptions; they are not measurements or undisclosed company behavior.
A viewer applied through 41. It replays to watermark 50 while live subscription buffers 49–53. Deduplicate the overlap and deliver 51–53 after the replay boundary; an unordered switch must not lose event 51.
Read the diagram
Viewer applied through 41; replay target watermark 50; Live subscription overlaps at 49 and 50; Apply overlap once, then continue with 51 onward; Expired cursor requires a declared reset
If a client reconnects beyond retained history, may the server pretend the old cursor is complete?
Show answer and explanation
Answer: No. Return a declared reset or current snapshot and explain the loss/recovery policy. Do not advance applied progress before application. Removed comments or revoked membership still need the serving policy, regardless of cursor validity.
FB Live Comments: Check the design
Observe fanout lag, buffer occupancy, forced resync and applied-cursor gaps. Test a gateway crash at the replay/live handoff and a client that never drains.