Grokking the System Design Interview, Volume II
Vote

0% completed

​

Step 10: Failure Modes and Operations

The consumer falls behind

A consumer crashes during a batch

A cache node fails

The counts drift

A region fails

What to watch

The complete design

YouTube Likes Counter: Failure Modes and Operations in System Design Interview II: Step 10: Failure Modes and Operations (Video)

The most dangerous failure in this system produces no error. The workers fall behind, the cached count on the page keeps rising correctly, and for several minutes nothing appears wrong, until a cache entry expires and thousands of viewers watch a popular video lose likes.

This lesson covers five ways the design fails and how it recovers from each. One repair stands behind all five: every total can be recomputed from the per-user rows in UserLikes.

Five failures with one repair behind them. The per-user rows make every count recomputable, so no failure leaves a total permanently wrong.
Five failures with one repair behind them. The per-user rows make every count recomputable, so no failure leaves a total permanently wrong.

The consumer falls behind

Kafka keeps every event until a consumer reads it. The distance between the newest event in a partition and the last one the consumer group has processed is the consumer lag, and a traffic spike, a slow database, or a worker restart all increase it.

Viewers do not see lag directly, because the cache updates on the write path; only ContentStats falls behind. A lag of several minutes becomes visible when a cache entry expires: the next read loads the older total, and the count drops.

The first repair is more consumer instances, up to one per partition, since each partition is read by only one consumer in a group. The second is a cache TTL longer than the worst lag the system will accept.

A consumer crashes during a batch

A replacement consumer resumes from the group's last committed offset, the last position it confirmed, so events that were applied but not yet committed arrive a second time. The versioned transitions from Step 8 make this safe, because the consumer skips any version it has already applied.

This depends on one ordering rule: commit the offset after the totals are written, never before. Replaying an event costs nothing, while skipping one leaves a wrong total that nobody detects until the recount runs.

A cache node fails

When a Redis node fails without a replica, its keys are gone, and the read path refills them from ContentStats. The refill must start from the durable total, because a cache that restarted a key at zero would show a video with 1.5 million likes as having 12.

Running Redis with replicas keeps the keys through a failover, the automatic switch to a standby copy. A refresh also never lowers a value already in the cache, because a lagging ContentStats read would otherwise move a visible count backward.

The counts drift

Over months, the totals in ContentStats will stop matching the rows in UserLikes. A transition lost in the small window from Step 8, a bug in one release, or a manual correction each adds a small difference, so the design treats drift as certain.

The repair is a recount job. For one item, it counts the matching rows in UserLikes, compares the result with ContentStats, and writes the counted value when they differ. It runs as a slow rolling pass over all content, and on demand, so support staff can correct one video immediately. This job is what the per-user rows are stored for: a design that kept only totals could never answer "is this number right?".

A region fails

Writes complete in their local region and replicate in the background, so losing one region does not stop the others. What is lost is the last second or so of reactions that had not yet left the failed region. Those reactions are missing until the region recovers, and the recount job then corrects the affected totals. A design that chooses availability should state this loss openly rather than claim zero loss.

What to watch

These six signals cover the failures above.

SignalWhy it mattersAct when
Consumer lag per partitionthe durable count is falling behindlag grows past the cache TTL
Cache hit rate on countsa drop sends read traffic to the databasebelow about 95 percent
Reconciliation driftmeasures whether the pipeline is correctany item off by more than a few
p95 write latencyStep 2 committed to under 100msover 100ms for five minutes
p95 read latencyStep 2 committed to under 20msover 20ms for five minutes
Vote endpoint error rateconditional write retries and store failuresover 0.1 percent

The complete design

A reaction is one conditional, versioned write to UserLikes, plus a Redis increment and a Kafka event in the same request. Workers apply each transition once to ContentStats, reads come from Redis, and a recount job corrects any drift. Redis meets the 20 ms read target, Kafka keeps writes under the 100 ms target during a spike, and the versioned write lets the design accept eventual consistency without accepting wrong numbers.

💡 In the interview: Raise a failure before the interviewer asks: "The failure I would watch most closely is the consumer falling behind. The cache still looks right while the durable count is stale, and when an entry expires, the visible number drops. I would tie the cache TTL to the lag I am willing to accept." Then mention the recount job, which answers most follow-up questions about correctness.

Key takeaway: This system is allowed to be wrong for a few seconds, and that permission is what lets it scale. It is not allowed to stay wrong without anyone noticing. The cache serves reads, the queue absorbs writes, and the recount from the per-user rows turns an eventually consistent count into one you can trust.

Reading Progress

0%


Vote for new content

On This Page

The consumer falls behind

A consumer crashes during a batch

A cache node fails

The counts drift

A region fails

What to watch

The complete design