The Problem Consistent Hashing Solves

Say you spread cached data across 4 servers with a simple rule:

server = hash(key) % 4

It works, until you add a 5th server. Now it's hash(key) % 5, and almost every key maps to a different server. Your cache misses everywhere at once, and the database behind it gets flooded.

Consistent hashing fixes this. When a server is added or removed, only a small fraction of keys move. That's why it sits at the heart of distributed caches and databases.


🎯 Quick Answer (30-Second Read)

  • Problem: with hash(key) % N, changing N remaps most keys.
  • Idea: place servers and keys on the same hash ring. Each key belongs to the next server clockwise.
  • Result: adding or removing a server moves only about 1/N of the keys, the ones near it on the ring.
  • Virtual nodes: each server takes many positions on the ring for a more even spread.
  • Used in: Amazon's Dynamo design, Apache Cassandra, memcached client libraries, and load balancers that need stable routing.

Why hash % N Breaks

With modulo hashing, a key's server depends on N. Change N, and the answer changes for most keys. For example, going from 4 to 5 servers keeps only about 1 in 5 keys on the same server. The other ~80% move.

Why it matters: for a cache, "keys move" means "cache misses". Remapping most keys at once can send a sudden wave of requests to the database. That's exactly the kind of overload that causes outages.

How the Hash Ring Works

  1. Imagine the range of hash values as a circle (0 at the top, wrapping round to the maximum).
  2. Hash each server (for example its name) to a point on the circle.
  3. Hash each key to a point on the circle.
  4. A key belongs to the first server clockwise from it.
flowchart LR K1([key: user:42]) -->|next clockwise| A[Server A] K2([key: cart:7]) -->|next clockwise| B[Server B] K3([key: img:99]) -->|next clockwise| C[Server C] style A fill:#312e81,color:#ffffff,stroke:#6366f1 style B fill:#1e3a5f,color:#ffffff,stroke:#3b82f6 style C fill:#166534,color:#ffffff,stroke:#16a34a

Adding a server D between A and B: only the keys between A and D (which used to go to B) move to D. Everything else stays put.

Removing server B: only B's keys move, to the next server clockwise (C). Nobody else is affected.


Virtual Nodes: Fixing Uneven Load

With only a few servers on the ring, the gaps between them can be very uneven, so one server ends up with far more keys.

The fix is virtual nodes: each physical server is placed on the ring many times (A#1, A#2, … A#100).

  • Load spreads far more evenly.
  • When a server leaves, its keys spread across many servers, not just one neighbour.
  • Bigger servers can get more virtual nodes, so they take a bigger share.

Simple Implementation (Python)

import bisect, hashlib

def h(value: str) -> int:
    return int(hashlib.md5(value.encode()).hexdigest(), 16)

class HashRing:
    def __init__(self, servers, vnodes=100):
        self.ring = {}              # position -> server
        self.positions = []
        for s in servers:
            self.add(s, vnodes)

    def add(self, server, vnodes=100):
        for i in range(vnodes):
            pos = h(f"{server}#{i}")
            self.ring[pos] = server
            bisect.insort(self.positions, pos)

    def remove(self, server, vnodes=100):
        for i in range(vnodes):
            pos = h(f"{server}#{i}")
            del self.ring[pos]
            self.positions.remove(pos)

    def get(self, key: str) -> str:
        pos = h(key)
        i = bisect.bisect(self.positions, pos) % len(self.positions)  # next clockwise, wrap around
        return self.ring[self.positions[i]]

ring = HashRing(["cache-a", "cache-b", "cache-c"])
print(ring.get("user:42"))

Add ring.add("cache-d") and compare key assignments before and after. Only a fraction of keys change server.


Where Consistent Hashing Is Used

System How it uses consistent hashing
Amazon Dynamo (2007 paper) Partitions data across storage nodes on a ring, with virtual nodes
Apache Cassandra Distributes data with a token ring, with virtual nodes (vnodes)
Memcached clients Client libraries map keys to cache servers so adding a server doesn't flush the whole cache
Load balancers Hash-based routing keeps a user or key on the same backend while servers change
CDNs and object stores Decide which node holds which object

Trade-offs and Alternatives

  • Still not perfectly even: it needs enough virtual nodes to balance well.
  • Hot keys: one very popular key still lands on one server. Use replication or caching to handle it.
  • Replication: systems often store each key on the next R servers clockwise for fault tolerance.
  • Alternatives: rendezvous (highest random weight) hashing and jump consistent hash give similar "minimal movement" properties with different trade-offs.

Frequently Asked Questions

What is consistent hashing in simple terms?

It's a way of assigning keys to servers so that when you add or remove a server, only a small portion of keys move. Servers and keys are placed on a circular hash ring, and each key goes to the next server clockwise.

Why are virtual nodes needed?

With only a few points on the ring, servers can end up with very unequal shares of keys. Virtual nodes place each server at many points, which evens out the load and spreads a departing server's keys across many others instead of one neighbour.

How many keys move when a server is added?

On average about 1/N of the keys, where N is the number of servers after the change. With modulo hashing, most keys move instead. That difference is the whole point of consistent hashing.


Conclusion

Consistent hashing maps keys and servers onto a ring so each key goes to the next server clockwise. Adding or removing a server then moves only about 1/N of keys instead of nearly all of them. Add virtual nodes for even load, and you have the foundation that distributed caches and databases like Dynamo and Cassandra are built on.


Sources

Last verified: 14 October 2026.


Related reads: Load Balancer Explained · Rate Limiter Explained · Redis Explained · How Discord Scaled

I write about system design and how real products are built. Follow on LinkedIn or X, or invite me to speak.