System Design
Consistent Hashing
the problem with hash(key) % N
Fast, simple, evenly distributed — until N changes. Adding or removing
a server changes every subsequent % N, which reassigns almost the
entire keyspace, not just the keys that logically should move.
A concrete example
3 nodes (A, B, C), 12 keys, routed by hash(key) % 3. Add a 4th
node (D) and recompute with % 4:
| key | N=3 owner | N=4 owner | moved? |
|---|---|---|---|
| session-42 | A | A | |
| session-77 | B | A | ✅ |
| cart-13 | C | C | |
| cart-88 | B | C | ✅ |
| user-5 | C | A | ✅ |
| user-9 | A | A | |
| user-21 | C | A | ✅ |
| order-3 | A | D | ✅ |
| order-14 | C | D | ✅ |
| view-1 | C | C | |
| view-2 | A | D | ✅ |
| view-3 | B | A | ✅ |
8 of 12 keys (67%) moved to a different server — for adding one machine. In a real cache cluster, that's 67% of your traffic suddenly missing cache and hammering the database at once. In a real DB shard map, that's a two-thirds data migration to add one node.
This is the failure mode consistent hashing exists to fix: it makes node changes touch a bounded, local slice of the keyspace instead of the whole thing.
Try the live version — add/remove nodes and watch the naive approach vs. the ring side by side: Consistent Hashing, Drawn on a Ring