Distributed counters
Counting is easy until everyone counts the same thing at once.
What problem does a sharded counter solve?
A view count, a like count, a rate meter. One row and an increment works fine, until thousands of writers hit the same row and all queue behind the same lock.
That row becomes a hot spot, and the fix depends entirely on whether the number has to be exact.
What a sharded counter costs you
Every concept in here states a cost. A technique with no price is a technique you have not understood yet — and naming the cost out loud is most of what separates a senior answer from a junior one.
When to reach for a sharded counter, and when not to
Use it when
- Any counter with many writers at once: views, likes, impressions, rate limits.
- Analytics totals where a small error is invisible.
- Counting distinct things over huge streams, like unique visitors, where being exact is not worth the memory.
Do not, when
- The count is a resource people compete for: remaining seats, stock, an account balance. That is not a counter problem, it is a transaction problem, and approximation is not on the table.
- Low write volume. One row and an increment is correct and simple.
How a sharded counter actually works
The write problem became a read problem. That is the trade: reads now add up 100 rows, so cache the total and refresh it every few seconds.
Sharded counters are the standard answer. Instead of one row, keep N rows for the same logical counter, and have each writer increment a random one. Contention drops by roughly N. Reading means adding up N rows, which you then cache. So the number on screen is a couple of seconds old, which users cannot notice on a view count.
Write batching goes further. Each application server keeps a count in its own memory and flushes it every second or two as a single increment. A thousand increments become one write. The cost: if the process dies, you lose whatever it had not flushed. For view counts that is fine, but say it out loud rather than hoping nobody asks.
For counts over time windows, an approximate structure is often right. HyperLogLog estimates distinct counts, like unique visitors today, in about 12 KB with under 1% standard error, whether you saw a thousand items or a billion. A count-min sketch estimates how often each key appears, which is how you spot a hot key or an abusive caller without tracking every one of them.
The distinction that decides the design: is this number a display, or a decision? A like count is a display, so approximate and slightly old is correct engineering. Remaining tickets is a decision, and it must be exact at the moment you commit. That is enforced by a conditional update or a constraint, not by a counter you read and then trust. Treat stock as a counter and you will oversell.
There is a middle case worth knowing: something that is a decision, but not about one specific item, like a rate limit. There an approximate count is usually fine, because letting through 105 requests instead of 100 rarely matters. So you can shard or batch, as long as you choose which direction the error goes.
- Treating stock as a counter. It is a resource people compete for.
- Adding up the shards on every request instead of caching the total.
- Losing in-memory batches without ever admitting that it happens.
The a sharded counter follow-up an interviewer will ask
"Your view counter is a single row and a post goes viral. What happens?"
Every increment for that post queues on one row lock. Throughput collapses to what one lock can process, latency climbs, and connections pile up waiting. And because those connections come from a shared pool, the damage spreads to endpoints that have nothing to do with view counts. So a hot row does not just make counting slow. It can take down neighbouring features. The fix is to stop making them compete. Batch increments in memory on each server and flush every second, and spread the stored counter over N shard rows so writers do not queue on one. Reads add up the shards and get cached for a few seconds. The costs are that the number can be a few seconds old, and that I lose unflushed counts if a server dies mid-flush. Both are entirely acceptable for views, and both are things I would refuse to accept for stock.
Your turn
When is a sharded counter the wrong answer? Give the specific case.
Learn it from the source
This page gets you interview-ready. These take you to where the idea is actually specified or measured — read them when you want the real depth.
- Redis — Bloom filters and probabilistic types ↗The same family of structures used when an exact count is too expensive.