Sharding is the act of splitting a data set across multiple machines so that no single machine holds everything. The naive approach — assign shard 0 to server A, shard 1 to server B — breaks the moment a server is added or removed: every key's assignment changes, and everything must be resharded. Consistent hashing solves this by making the mapping of keys to servers independent of the server set.
The modulo problem
If you assign a key to server = servers[hash(key) % N], then adding one server changes N to N+1, and every key's modulo result changes. In practice, you rehash the entire dataset. For a database with 10 TB of data, that is a multi-day operation of copying data across the network. No production system does this.
How consistent hashing works
Place each server at a random position on a hash ring. To place a key, hash it, walk the ring clockwise, and assign it to the first server encountered. When a server is added to the ring, only the keys between it and the previous server on the ring move — the rest stay put. When a server is removed, only its keys are reassigned. The movement is bounded to 1/N of the key space, not 100%.
Virtual nodes: why one position per server is not enough
A single position per server means server placement on the ring is random — one server might get 30% of the ring, another gets 2%. To smooth this out, each physical server gets many virtual nodes (vnodes) — say, 150 positions on the ring. The keys are distributed more evenly, and when a server fails, its load is spread across many remaining servers instead of concentrating on one neighbor.
The shard key: what you hash matters
The shard key determines how data is distributed and how it can be queried. A good shard key distributes evenly across the hash space and is the primary lookup key. A bad shard key creates hot spots — all writes to the same user end up on the same shard, and that shard's server becomes the bottleneck.
The shard key also determines what queries are cheap and what queries are expensive. If you shard by user ID, finding a user by ID is a single shard hop. Finding all users in a city requires querying all shards — a scatter-gather query that is O(shards) in cost.
Where consistent hashing appears
Consistent hashing is not limited to databases. The load balancer article describes how a load balancer can use the same technique to route requests to backend instances — the request hash determines the backend, and adding or removing backends only reassigns the affected hash range. The rate limiter practice uses the same idea to distribute counters across multiple Redis instances.
The circuit breaker and bulkhead article explains how to handle the failure case — when a shard goes down, the circuit breaker prevents retry storms, and the bulkhead prevents the failure from cascading to other shards.