a counter that gets hit far too often to live on one row

A popular restaurant's "total orders" or "likes" count is a single number, but at high popularity it can be incremented by thousands of concurrent requests per second. A naive UPDATE restaurants SET order_count = order_count + 1 forces every one of those concurrent writers to serialize on the same database row β€” the row itself becomes a bottleneck, sometimes called a hot key, no matter how well the rest of the system is sharded.

the fix: split one counter into many

A sharded counter replaces a single row with several β€” say, 10 shards β€” each holding a fraction of the true count. An increment picks one shard (often at random, or round-robin) and updates only that shard, spreading concurrent write load across all 10 instead of funneling it through one.

order_count_shard_0 = 4213
order_count_shard_1 = 4198
order_count_shard_2 = 4256
...
order_count_shard_9 = 4177

total = sum(all shards)  # computed at read time, or periodically cached
            
Reading the total requires summing across shards, which is more work than reading a single row β€” but reads of an aggregate count are typically far less frequent and less latency-sensitive than the writes that increment it, so this trade generally favors the write-heavy side of the workload.

how many shards, and where to place them

The number of shards is a direct dial on write throughput: more shards means less contention per shard, at the cost of more work to compute the total on read. A counter for a viral, globally popular item might need many more shards than a rarely-updated one β€” this is often tuned dynamically, starting with few shards and adding more if a specific counter is detected as a hot key.
Placement also matters for latency: shards can live near the application servers that increment them most, or even be cached at the edge for extremely high-traffic counters (e.g. a live view-count on a trending item), syncing back to durable storage periodically rather than on every single increment.

making reads cheap: periodic aggregation

For counts that are read far more often than the raw per-shard values need to be exact in real time (a restaurant's public "orders served" badge, for instance), a background job can periodically sum the shards and cache the total β€” trading a small amount of staleness for reads that don't have to fan out across every shard on every request. This mirrors the same eventual-consistency trade-off seen throughout this track: exact-and-slow vs. approximate-and-fast, chosen per feature rather than applied uniformly.

when sharded counters are worth the complexity

Use a sharded counter when…A plain counter is fine when…
The counter is incremented by many concurrent writers (likes, views, trending items)Updates are infrequent or naturally serialized (a single restaurant's own inventory count)
Write contention on one row is a measured, real bottleneckThere's no evidence of contention β€” this is a targeted fix, not a default
This is a narrow, specific tool: it solves exactly one problem (write contention on a single hot aggregate value) and adds real complexity (summing shards, choosing a shard count) that isn't worth paying for a counter that was never actually a bottleneck.

related topics

reference