Live Comments System Design
Build live comments as a durable broadcast pipeline: server-assign seq per stream, persist + publish to a log, fan-out to gateways, dedupe on clients, catch up via last_seen_seq, make moderation “must win,” and degrade hot streams with sampling/slow mode while
Live comments are the engine of real-time interaction on the internet. They power experiences like Twitch chats, YouTube Live comment feeds, live sports reactions, breaking news discussions, and collaborative tools where many people watch the same “stream” simultaneously. What makes live comments special is the broadcast shape: one stream can have 100,000+ concurrent viewers, but only a small fraction are actively posting at any moment.
Interviewers love this problem because it’s a concentrated test of large-scale broadcast design. You need low latency, massive fan-out, strict per-stream ordering, burst tolerance during peak events, and a safety system that can retract or suppress harmful content instantly. Unlike static commenting (which can tolerate seconds of delay), live comments demand persistent connections and a system that behaves well when parts crash.
This blog is structured like a Staff-level system design interview answer: clarify guarantees, propose a pipeline, explain ordering, build a comment lifecycle state machine, handle cold start and catch-up, design moderation as a control plane, and finish with hot-stream degradation strategies and observability.
System Design Interviews decide your level and compensation at top tech companies. To succeed, you must design scalable systems, justify trade-offs, and explain decisions under time pressure. Most candidates struggle because they lack a repeatable method. Built by FAANG engineers, this is the definitive System Design Interview course. You will master distributed systems building blocks: databases, caches, load balancers, messaging, microservices, sharding, replication, and consistency, and learn the patterns behind web-scale architectures. Using the RESHADED framework, you will translate open-ended system design problems into precise requirements, explicit constraints, and success metrics, then design modular, reliable solutions. Full Mock Interview practice builds fluency and timing. By the end, you will discuss architectures with Staff-level clarity, tackle unseen questions with confidence, and stand out in System Design Interviews at leading companies.
Interviewer tip: Don’t design “chat.” Design “broadcast.” The hardest part isn’t accepting comments—it’s safely and cheaply delivering them to huge audiences under burst load.
Clarify requirements and state the guarantees you can defend#
A strong interview answer begins by locking scope and explicitly stating the guarantees. Live comments commonly include: posting comments, receiving comments in near real time, reactions, and moderation (delete/hold/ban). But the differentiator is what you promise under failure: whether you can lose comments, whether duplicates can happen, how you order messages, and how fast moderation actions propagate.
The safest and most scalable delivery contract is at-least-once delivery with client deduplication. Under crashes, the system can’t always know whether a client received an event, so retries can cause duplicates. Losing comments is worse for engagement, so you accept duplicates and make them harmless through IDs and sequence numbers.
Ordering is where many candidates get trapped. You cannot rely on timestamps alone because clock skew, variable network delays, and replays will reorder events. The stable approach is per-stream ordering using server-assigned sequence numbers. That sequence becomes the canonical ordering key for rendering and for catch-up.
Area | Interview-friendly guarantee | Why it’s realistic |
Delivery | At-least-once (duplicates possible) | Crash ambiguity forces retries |
Ordering | Per-stream total order via server sequence | Timestamps fail under skew and retries |
Durability | Persist comments + retain a replayable log | Recovery and catch-up depend on it |
Moderation | “Moderation must win” within tight latency | Safety is non-negotiable |
Reactions | Eventually consistent aggregation | High volume; correctness is approximate |
Common pitfall: Saying “exactly once” or “use timestamps for ordering” without acknowledging clock skew and retries. Interviewers hear that as “hasn’t operated real-time pipelines.”
Summary (after the explanation):
Commit to at-least-once delivery with client dedupe.
Use server-assigned per-stream sequence numbers for ordering.
Persist comments and keep a replayable log for recovery.
Treat moderation as a top-priority path with strict propagation goals.
High-level architecture: a durable event pipeline with a fast broadcast edge#
A live comments system is easiest to reason about as a pipeline: ingest → validate → order → persist → publish → fan-out. You want the ingest path to be fast and rate limited, the ordering point to be explicit, and the fan-out layer to be able to push to massive numbers of connected clients efficiently.
At the edge, you typically use WebSockets or Server-Sent Events (SSE) to keep a persistent channel open. Gateways focus on connection management and efficient pushing, not business logic. Behind the gateways, an ingestion service authenticates users, enforces per-user and per-stream limits, and forwards accepted comments into a durable log (Kafka or similar). Fan-out workers then consume the log and broadcast new events to the correct stream’s connected clients.
The “single source of truth” should be the durable log plus the database that stores comment history. The log supports replay and recovery; the database supports cold start history load and post-stream playback. Caches are used for stream membership and connection mapping, not as truth.
Client | Render, dedupe, maintain last_seen_seq, reconnect | Correctness depends on sync behavior |
Realtime gateway | Maintain connections; push events to viewers | Stateless, horizontally scaled |
Ingestion service | Auth, validation, rate limits, initial moderation checks | Fast path; rejects early |
Sequencer/ordering | Assign per-stream sequence numbers | Can be embedded in ingestion or separate |
Durable log/stream | Persist events; allow replay; buffer bursts | Backbone for recovery |
Fan-out workers | Consume log; broadcast to gateways | Optimized for high throughput |
Comment store | Durable history by (stream_id, seq) | Used for cold start and catch-up |
Moderation control plane | Decide holds/deletes/bans; emit moderation events | Must preempt display |
Interviewer tip: Say where the “ordering point” lives. It’s your system’s most important invariant for rendering and catch-up.
Summary (after the explanation):
Use gateways for push connections, not business logic.
Make ordering explicit with a sequencer or ordered ingestion step.
Use a durable log for replay, buffering, and fan-out input.
Keep comment history in a store keyed by (stream_id, seq).
Ordering and sequencing: why timestamps fail and how sequence numbers work#
Ordering is not just “nice to have” in live comments—it’s what makes the feed readable. In distributed systems, timestamps are unreliable ordering keys: clients have skewed clocks, servers may differ by milliseconds to seconds, and retries can cause late arrivals. Even server timestamps can reorder across shards or hosts unless you pay for strong coordination.
The practical answer is: for each stream, assign a monotonically increasing sequence number at the moment the comment is accepted. That sequence becomes the canonical ordering key used everywhere: clients render in seq order, the database stores comments clustered by seq, and catch-up queries are “give me comments after seq N.”
How do you generate sequence numbers? In interviews, there are two defensible patterns. The first is a dedicated sequencer partitioned by stream_id (consistent hash), which increments a per-stream counter. The second is leveraging a log that provides per-partition ordering by ensuring all events for a stream go to the same partition, and using the log offset as the sequence. Both work; the key is to keep the mapping stable so a stream doesn’t bounce partitions frequently.
Sequencer service | Per-stream counter | Clear semantics; independent of log | Extra service; hot streams can stress it | Many streams, predictable ordering needs |
Log offset as seq | Kafka partition offset | No extra service; built-in ordering | Requires stable partitioning; re-partitioning tricky | Already using Kafka heavily |
Timestamp ordering | Wall clock | Simple | Incorrect under skew/retries | Almost never acceptable |
What great answers sound like: “I don’t order by timestamps. I assign a server sequence per stream, and everything—rendering, storage, catch-up—keys off that sequence.”
Summary (after the explanation):
Timestamps are not a reliable ordering key under skew and retries.
Use server-assigned per-stream sequence numbers.
Keep sequence generation stable by stream partitioning or a sequencer.
Data model: store once, read sequentially, and make moderation reversible#
Live comments data access is dominated by sequential reads: when a user joins, you load the most recent window; when catching up, you fetch comments after a sequence number. That’s a perfect fit for a store where (stream_id) is the partition key and (seq) is the clustering key.
You also need moderation metadata and an audit trail. Deletions should be soft deletes: keep the comment row, mark it as deleted/hidden, and record who took the action and why. This preserves the sequence timeline and supports appeals, audits, and future safety model improvements.
If you support reactions, avoid writing a new record per reaction at massive scale. A common approach is to store reaction events in a log and maintain aggregated counters per stream (or per comment for smaller volumes), with eventual consistency.
Comment | (stream_id, seq) | comment_id, user_id, content_ref, created_at, state | Ordered history + rendering |
Comment index (optional) | comment_id | stream_id, seq | Fast lookup for moderation actions |
Moderation record | moderation_id | actor_id, action, target, reason, timestamp | Audit trail and compliance |
Stream metadata | stream_id | title, status, policy knobs (slow mode) | Control-plane configuration |
Reaction aggregates | (stream_id, window) | counts by reaction type | Scalable, eventually consistent UI |
Common pitfall: Hard-deleting comments from storage. That breaks auditability and can create confusing gaps in the sequence timeline.
Summary (after the explanation):
Optimize storage for sequential reads by (stream_id, seq).
Use soft deletes and keep a moderation audit trail.
Treat reactions as aggregated signals, not necessarily durable per-click records.
Comment lifecycle state machine: correctness through explicit states#
A broadcast system becomes interview-grade when you can describe the comment lifecycle as a state machine. Comments are not just “sent”; they pass through validation, ordering, persistence, publication, visibility, and potential moderation actions. Making these states explicit helps you reason about retries, duplicates, and “moderation must win” behavior.
A practical design persists the comment early (after validation and sequencing), then treats delivery as at-least-once. Visibility on clients is derived from receiving the comment event and the current moderation state. If a comment is later deleted, clients retract it by applying a delete event that references the original comment_id/seq.
RECEIVED | Ingestion accepted request | Request metadata, rate-limit counters | → VALIDATED, REJECTED |
VALIDATED | Auth/validation passed | comment draft + user/stream refs | → SEQUENCED |
SEQUENCED | Canonical order assigned | (stream_id, seq) reserved/assigned | → PERSISTED |
PERSISTED | Stored durably | Comment row + initial state=VISIBLE | → PUBLISHED, HELD, DELETED |
PUBLISHED | Event emitted to log | Log record with seq, comment_id | → VISIBLE (client), RETRACTED |
HELD | Held for review (not visible) | State=HELD + moderation record | → VISIBLE, DELETED |
DELETED | Soft-deleted / retracted | State=DELETED + moderation record | terminal (or appeal workflow) |
Interviewer tip: The state machine is how you prove you’ve thought about retries, replays, and moderation retractions. Without it, your design is a diagram, not a system.
Summary (after the explanation):
Model comment handling as explicit states with persisted transitions.
Persist before publication to guarantee durability and replay.
Use delete/retract events keyed by comment_id/seq for instant retractions.
Walkthrough 1: user posts a comment and all viewers receive it fast#
A user types a comment and hits send. The client sends a request to the ingestion service (often through a gateway). Ingestion authenticates the user, validates the payload, applies rate limits (per user and per stream), and runs lightweight safety checks. If accepted, it assigns the next sequence number for that stream and persists the comment row with state=VISIBLE (or HELD if policy requires review).
Next, ingestion publishes a “comment created” event to the durable log with (stream_id, seq, comment_id). Fan-out workers consume this event and broadcast it to the gateways responsible for that stream’s connected viewers. Gateways push the event down WebSocket/SSE. Each client deduplicates by (comment_id or seq), inserts the comment into the UI in sequence order, and updates last_seen_seq.
If a viewer is slightly behind or their network jitters, they may receive comments out of order. The sequence number lets the client buffer and re-sequence. If a comment is missing, the client’s catch-up flow (covered later) pulls it from history using last_seen_seq.
What great answers sound like: “Persist, publish to a durable log, then fan-out. Clients order by server sequence and dedupe by ID. If anything is missed, catch-up fills the gaps.”
Summary (after the explanation):
Validate and rate limit before sequencing.
Persist comment and publish an event to a durable log.
Fan-out workers broadcast to gateways; gateways push to clients.
Clients render by sequence and dedupe by comment_id/seq.
Cold start and catch-up#
Cold start and catch-up are where real-time broadcast systems prove correctness. When a viewer joins a stream (or reconnects after a disconnect), they should see a recent window of comments quickly and then seamlessly catch up to the live edge. Relying solely on “whatever arrives over WebSocket” guarantees gaps, especially on mobile networks.
A solid approach is: on join, the client calls a history API to fetch the last N comments (for example, last 50–200) ordered by sequence. The response includes the latest sequence number the server considers “current.” The client then opens a live connection and starts receiving new events. If the client detects it is behind (gaps in sequence), it issues a catch-up request: “give me comments after last_seen_seq.”
This design also supports reconnect. After a connection drop, the client reconnects and provides last_seen_seq. The server streams or returns the missing range. This is the same mental model as reliable chat: persistent push is a latency optimization, but catch-up is the correctness mechanism.
| Cold start recent window | stream_id, limit | ordered comments, current_seq |
| Catch-up range | stream_id, last_seen_seq | missing comments (S+1..current) |
(optional) | Establish live session metadata | stream_id, last_seen_seq | token, resume_seq/current_seq |
| Submit a comment | stream_id, content, idempotency key | comment_id, assigned seq |
(optional) | Catch-up moderation events | stream_id, last_mod_seq | moderation changes |
What interviewers look for in reconnect/catch-up answers: “I want to hear last_seen_seq, gap detection, and a history-based catch-up path that works even if the realtime channel dropped events.”
Summary (after the explanation):
Join = load recent window + begin live subscription.
Catch-up = fetch comments after last_seen_seq to fill gaps.
Reconnect uses the same catch-up primitive; push is an optimization.
Moderation as a control plane#
Moderation is not “just another event.” It is a control plane that must override the data plane. Comment events are high volume and user-generated; moderation events are lower volume but higher priority and must propagate reliably and quickly. If your system treats them as the same stream with equal priority, you will eventually display content that should have been removed.
A strong design models moderation decisions as separate events: delete, hold, approve, shadow ban, user mute, stream slow mode, and escalation flags. These events reference targets (comment_id/seq, user_id, stream_id) and carry an audit trail. Clients subscribe to moderation events for the stream and apply them immediately by retracting or hiding affected content. Soft deletes preserve data for auditing while ensuring clients remove it from view.
Advanced but interview-friendly concepts include “held for review” (comment is persisted but not visible until approved) and shadow bans (a user’s comments appear to themselves but are hidden from others). Both require careful separation of visibility rules from raw storage and benefit from moderation being a control plane with explicit policies.
Soft delete comment | state → DELETED | Retract immediately | Who/why/when |
Hold for review | state → HELD | Do not render (or show placeholder) | Queue + reviewer decision |
Shadow ban user | filter visibility for others | Hide user’s comments from others | Traceable policy decision |
Slow mode | throttle comment submit rate | UI indicates rate limit | Policy change record |
Moderation must win: “If moderation and comments disagree, clients must converge to the moderation outcome quickly, even during hot-stream degradation.”
Summary:
Treat moderation as a separate control plane with higher priority.
Use soft deletes, holds, shadow bans, and auditable actions.
Clients apply moderation events immediately to retract/hide content.
Walkthrough 2: moderator deletes a comment and all clients retract it immediately#
A comment is visible to viewers, but a moderator decides it violates policy. The moderator dashboard issues a delete action referencing the comment_id (and optionally stream_id, seq). The moderation service records an audit entry and updates the comment state to DELETED (soft delete). It then publishes a moderation event to a high-priority moderation stream.
Gateways and fan-out workers deliver moderation events quickly—often on a separate channel or with strict priority scheduling. Clients receiving the delete event remove the comment from the UI immediately. If the comment is not currently loaded (because the viewer joined later), the deletion still matters: when the client loads history, the server can either exclude deleted comments or include tombstones that instruct the client not to render them.
This is where “moderation must win” becomes concrete. Even if a client is behind on comment events, the moderation event should apply as soon as it arrives, preventing the comment from reappearing during catch-up replay.
Common pitfall: Only deleting in the database but not emitting a realtime retract event. In live systems, users need immediate retraction, not eventual consistency.
Summary (after the explanation):
Persist moderation action with an audit trail.
Emit a high-priority moderation event for realtime retraction.
Clients retract immediately and remain consistent during history loads.
Hot streams and graceful degradation#
Hot streams are inevitable: major sports finals, celebrity live streams, breaking news. In these cases, the system becomes constrained not by storage, but by fan-out bandwidth, gateway CPU, and queue lag. A Staff-level answer describes how you detect hot streams early and degrade gracefully while keeping the experience usable and moderation effective.
Detection comes from telemetry: publish rate per stream, queue lag per stream partition, gateway outbound pressure, client drop rates, and fan-out success rate. If one stream’s metrics spike, you treat it as a localized overload and apply stream-scoped mitigations rather than global throttling.
Degradation tactics should be explicit and user-visible. Common strategies include sampling comments (show only a subset), enabling slow mode (throttling comment submission), aggregating reactions (send periodic counters rather than individual events), dropping low-priority events (typing-like signals, if any), and prioritizing moderation events over comment events. The key is to map triggers to mitigations and be clear about user impact.
Publish rate exceeds threshold | Slow mode (per stream) | Fewer comments can be posted |
Queue lag rising | Sampling comments sent to viewers | Some comments not shown live |
Gateway CPU/network pressure | Reduce payload size; compress; batch sends | Slightly delayed or coarser updates |
Fan-out success rate drops | Prioritize moderation; drop non-critical events | Safety preserved; less “full fidelity” chat |
Reaction event flood | Aggregate reactions per window | Reactions update in batches |
Reconnect rate spike | Increase history window; enable catch-up batching | Longer initial load; fewer gaps |
Interviewer tip: Degradation isn’t failure. It’s a designed mode. Your answer should include “how we keep the system stable and safe when the stream is hotter than capacity.”
Summary (after the explanation):
Detect hot streams via per-stream publish rate, lag, and gateway pressure.
Apply stream-scoped mitigations: slow mode, sampling, aggregation, batching.
Always prioritize moderation propagation during degradation.
Reliability, duplicates, and replay: how the system heals after crashes#
Distributed broadcast systems crash. Gateways restart, workers roll, partitions rebalance. If your design requires perfect delivery over a single connection, it will lose events. The interview-friendly guarantee is at-least-once with client dedupe, supported by replay from a durable log and catch-up from history.
Duplicates happen when a worker sends an event and crashes before recording progress, or when clients reconnect and re-fetch a range that overlaps what they already received. Deduplication is straightforward if events carry stable identifiers. For comments, the pair (stream_id, seq) is often sufficient. For moderation events, include a moderation_seq or moderation_id. Clients keep a small dedupe window and ignore repeats.
Replay matters for recovery. If a fan-out worker crashes, it should resume consuming from the last committed offset. If gateways lose a stream subscription mapping temporarily, clients will reconnect and catch up using last_seen_seq. The durable log provides the “spine,” and the history store provides the “truth” for missed ranges.
Gateway crash | Clients disconnect; in-flight events may be missed | Reconnect + catch-up from last_seen_seq |
Worker crash after publish | Duplicate broadcast possible | Client dedupe by (stream_id, seq) |
Partition rebalance | Temporary lag spike | Log replay; backpressure; hot-stream mitigation |
Cache loss | Stream→gateway mapping rebuilt | Clients resubscribe; gateways rebuild state |
What great answers sound like: “I assume duplicates and missed realtime events happen. The system heals via replay from the log and catch-up from sequence-based history, with client dedupe.”
Walkthrough 3: gateway/worker crash causes duplicate delivery, and dedupe + replay fixes it#
A fan-out worker consumes comment seq=9001 and broadcasts it to gateways. Some clients receive it. Before the worker commits its offset (or before it records delivery progress), the worker crashes. On restart, it reprocesses the same log entry and broadcasts seq=9001 again.
Clients receive the duplicate. Because they render by seq and maintain a recent seen-set, they drop the second copy. If a client missed the first copy due to a connection drop, it still gets the second copy, so at-least-once delivery improves reliability. Meanwhile, a client that missed both copies reconnects later and requests catch-up after last_seen_seq=8995, fetching 8996..current from the history store.
Summary (after the explanation):
Crashes create duplicates; duplicates are acceptable under at-least-once.
Client dedupe by seq/comment_id makes duplicates harmless.
Replay from the log and catch-up from history close delivery gaps.
Observability: metrics that prove “live” and “safe”#
In real-time broadcast, the system’s health is measured in latency and lag, not just throughput. You should instrument the submit path (how fast a posted comment becomes visible), the fan-out path (success rate and gateway pressure), the moderation path (how fast retractions propagate), and the catch-up path (how often clients reconnect and how far behind they are).
A strong interview answer names concrete metrics and explains what they mean operationally. You also want per-stream breakdowns, because broadcast incidents are often localized: one stream is hot while others are normal.
p95 submit→visible latency | User-perceived “liveness” | Core UX KPI |
Queue lag per stream partition | Backpressure and overload | Early hot-stream detection |
Fan-out success rate | Delivery reliability | Detect gateway failures and saturation |
Moderation propagation latency | Safety responsiveness | “Moderation must win” enforcement |
Reconnect rate | Connection stability | Indicates gateway/network issues |
Drop/sampling rate | Degradation intensity | Helps tune mitigations and transparency |
Interviewer tip: If you can’t tell the interviewer how you’ll detect a hot stream before it melts the system, you haven’t finished the design.
Summary:
Measure submit→visible latency, queue lag, and fan-out success rate.
Track moderation propagation latency as a first-class SLO.
Monitor reconnect and drop/sampling rates to understand degradation.
Trade-offs you should say out loud#
Live comments systems live on trade-offs: fidelity vs stability, strictness vs cost, and safety vs throughput. A Staff-level answer acknowledges these explicitly and ties them to product choices. For example, sampling comments reduces fidelity but preserves the feeling of liveness. Aggregating reactions reduces granularity but avoids overwhelming clients and gateways. Using at-least-once increases duplicates but prevents loss.
Your trade-offs should also reflect that moderation is not optional. If the system is overloaded, you may choose to drop or sample comment events before you ever delay moderation retractions. This is one of the most important “senior” signals: prioritizing safety and correctness under stress.
Delivery semantics | Exactly-once | At-least-once + dedupe | At-least-once |
Ordering key | Timestamps | Server seq per stream | Server seq |
Hot-stream behavior | Full fidelity | Degrade gracefully | Degrade with transparency |
Moderation coupling | Same channel as comments | Separate control plane | Separate control plane |
Common pitfall: Treating degradation as “dropping messages randomly.” Degradation should be policy-driven, stream-scoped, and observable.
Summary (after the explanation):
Prefer at-least-once delivery with dedupe for reliability.
Use server sequence numbers for correct ordering.
Design explicit degradation modes for hot streams.
Keep moderation as a separate, higher-priority control plane.
What a strong interview answer sounds like#
A strong answer is short, structured, and decisive. You state the broadcast nature and the guarantees, then outline the pipeline, then zoom into ordering, catch-up, moderation, and degradation. You finish with metrics and failure recovery.
Sample 30–60 second outline: “Live comments are a broadcast system where one stream can have 100k+ viewers. I’ll use WebSockets/SSE gateways for persistent connections, an ingestion service that authenticates, rate limits, and assigns a per-stream sequence number for ordering, then persist the comment and publish it to a durable log like Kafka. Fan-out workers consume the log and broadcast to gateways; clients render by sequence and dedupe for at-least-once delivery. Join and reconnect use cold-start history plus catch-up from last_seen_seq to fill gaps. Moderation is a separate control plane: deletes/holds/shadow bans emit high-priority moderation events that must win and trigger immediate retractions. For hot streams, I detect lag and gateway pressure and degrade with slow mode, sampling, and reaction aggregation while prioritizing moderation. I’ll track p95 submit→visible, queue lag, fan-out success, moderation propagation latency, reconnect rate, and drop/sampling rate.”
Checklist (max 6 bullets):
Broadcast framing + explicit guarantees (at-least-once, per-stream ordering)
Server sequence numbers (why timestamps fail)
Durable log + replay and a history store keyed by (stream_id, seq)
Cold start + catch-up via last_seen_seq
Moderation as a separate, high-priority control plane
Hot-stream degradation + concrete metrics/SLOs
Interviewer tip: The best answers make failure and overload part of the design, not an afterthought.
Happy learning!
Free Resources