Sharded counter

One database row can take only one update at a time. If 3,000 increments each second hit 1 row, they wait in line. A sharded counter spreads them over 64 rows and adds the rows when you read the total.

Play a level

See it on the board

The same traffic runs on two boards. The simulator measured both when this page was built.

Board to show
SQLUsersPostgres2 vCPU · 2 GB
SQLUsersPostgres2 vCPU · 2 GB
All writes hit 1 row: misses a goal
SQLUsersPostgres2 vCPU · 2 GB
SQLUsersPostgres2 vCPU · 2 GB
Writes spread over 64 rows: meets the goals
See it on the board
Measure Goal All writes hit 1 row Writes spread over 64 rows
p99 latency under 100 ms 10.1 s Fail 27 ms Pass
CPU use under 80% 660% Fail 69.4% Pass
Monthly cost 8 USD/mo 8 USD/mo
Error rate 88.8% 0%

Key numbers

Default part values from the catalog. The mini board increments one counter 3,000 times each second.
NumberValue
Writes per second, one database vCPU2,500 writes/s
Disk sync time for one commit0.4 ms
Queries per second, one database15,000 ops/s
A counter split over many rowsTap or press Space to shard the counter

64 rows · busiest row 47 writes/s, a row takes 2,500 · the line grows by 0/s

How it works

A counter looks simple: read the number, add 1, write it back. The database protects the row with a lock, so two updates of the same row cannot run at once. Each update waits for the one before it.

In the mini board 3,000 writes/s increment one logical counter. All of them hit one row, so they take turns. The row becomes the limit, however many CPUs the database has. Waits grow, and p99 and CPU pass the limits.

A sharded counter splits the number over many rows, here 64. Each increment picks one row, so updates to different rows do not wait for each other. A read adds the rows together. A background step can also add the rows for a short interval, such as 1 s, and store the sum.

The trade-off is on the read side. The total costs a sum of 64 rows, or it can be up to one interval old. A counter that must be exact at every instant needs another design. Also pick the number of rows from the write rate: too few rows still queue, too many make reads slow.

In the levels you split a hot row so that writes run in parallel.