Consistent Hashing: Demystifying the Algorithm and Its Simple Implementation

Arpit Bhayani

Arpit Bhayani

Sep 01, 2026 • 8 min read

Play

Note: This article is an AI-generated write-up based on the captions and transcript of the video above. Watch the embedded video for the full visual walk-through and nuances.

Consistent Hashing: Demystifying the Algorithm and Its Simple Implementation

Consistent Hashing is one of the most frequently discussed and often misunderstood algorithms in system design. Many mistakenly view it as a magical solution or a complex service. In reality, it’s a remarkably simple algorithm designed to solve a specific problem: determining data ownership in a cluster with minimal disruption when the cluster topology changes.

This article aims to provide a clear mental model and intuition for consistent hashing, focusing on its core principles and straightforward implementation.

What Consistent Hashing Is (and Is Not)

Before diving into the mechanics, it’s crucial to clarify what consistent hashing is and what it isn’t:

  • Not a Silver Bullet: It doesn’t magically solve all scaling problems. It’s a tool for a specific use case.
  • Not a Service: Consistent Hashing is an algorithm, not a standalone service. It’s typically a few lines of code integrated into your application, load balancer, or proxy.
  • Solves Data Ownership: Its primary purpose is to answer the question: “Given a key (data, request, entity), which node in a cluster owns it?”
  • Minimizes Ownership Changes: Its key benefit is ensuring that when nodes are added or removed from a cluster, the number of keys whose ownership changes is minimized.

The Problem: Inefficient Data Ownership with Classic Hashing

In a distributed system, you need a way to map data or requests to specific nodes. A common, naive approach is hash-based ownership using the modulo operator:

node_index = hash(key) % N

Where N is the total number of nodes in the cluster.

Limitations of Classic Hashing

While simple, this hash(key) % N approach suffers from a critical flaw: high ownership changes when the number of nodes (N) changes. Consider a scenario where you have N nodes, and you add or remove just one node, changing N to N+1 or N-1.

Let’s visualize this with an example:

  • Initial State: hash(key) % 4 (4 nodes: 0, 1, 2, 3)
  • After Node Addition: hash(key) % 5 (5 nodes: 0, 1, 2, 3, 4)

Even a small change in N can drastically alter the node_index for most keys. For instance, a key that previously mapped to node 0 might now map to node 4. This means a significant portion of your data (or requests) would need to be re-routed or, in the case of stateful data, physically moved to new nodes. The video illustrates this, showing that out of 12 example keys, 10 had their ownership changed when N went from 4 to 5.

This extensive data movement or re-routing is highly inefficient and can lead to significant operational overhead and performance degradation in an elastic, dynamic environment.

Consistent Hashing: The Ring Topology Mental Model

Consistent Hashing addresses this problem by introducing a conceptual “ring” or a circular hash space.

How it Works (Conceptual Model)

  1. Hash Space: Imagine a large, circular hash space (e.g., from 0 to 2^32 - 1, or 0 to 2^256 - 1 for SHA-256). This is the “ring.”

  2. Node Placement: Each node in the cluster is assigned a position on this ring. This position is typically determined by hashing the node’s identifier (e.g., IP address, hostname) using the same hash function used for keys.

  3. Key Placement: When a key arrives, it is also hashed to determine its position on the same ring.

  4. Ownership Rule: To find the owner of a key, you traverse the ring clockwise from the key’s position until you encounter the first node. That node is designated as the owner of the key.

    Example: If key_62 hashes to a certain point on the ring, and the first node encountered clockwise from that point is N2, then N2 owns key_62.

The Benefit: Minimal Ownership Changes

The true power of consistent hashing becomes apparent when the cluster topology changes:

  • Adding a Node: If a new node (N_new) is added to the ring, it only takes ownership of keys that previously belonged to the next node clockwise from N_new. Keys on other parts of the ring remain unaffected. For example, if N_new is placed between N4 and N2, only keys that previously mapped to N2 (and were between N4 and N2) will now map to N_new. All other keys retain their original owners.
  • Removing a Node: If a node (N_removed) is removed, its keys are re-assigned to the next node clockwise on the ring. Again, only the keys previously owned by N_removed are affected; the rest of the ring remains stable.

This mechanism ensures that only a small fraction of keys (roughly 1/N where N is the number of nodes) are affected by a topology change, leading to significantly less data movement and re-routing compared to classic hashing.

Implementing Consistent Hashing from First Principles

The “ring” visualization is a mental model, not a literal data structure. You wouldn’t create a linked list of 2^256 elements or an array of that size. The actual implementation is much simpler.

The Sorted Array Approach

The core idea is to leverage the sorted nature of the node positions on the conceptual ring:

  1. Node Positions Array: Create an array that stores the hash values (positions on the ring) of all active nodes. This array must be kept sorted in ascending order.
  2. Key Lookup: When a key comes in: a. Hash the key to get its position on the ring (key_hash). b. Perform a lookup in the sorted array of node positions to find the first node position that is greater than or equal to key_hash. c. The node corresponding to this found position is the owner. d. Wrap-around: If key_hash is greater than all node positions in the array (meaning it falls past the last node on the ring), the key wraps around and is assigned to the first node in the sorted array (which corresponds to the smallest hash value on the ring).

This lookup is essentially finding the “ceiling” or “upper bound” in a sorted list.

Pseudocode Example (Conceptual)

class ConsistentHasher:
    def __init__(self, nodes):
        self.nodes = {}
        self.sorted_node_hashes = []
        self.hash_function = lambda x: hash(x) # Placeholder hash function

        for node_id in nodes:
            node_hash = self.hash_function(node_id)
            self.nodes[node_hash] = node_id
            self.sorted_node_hashes.append(node_hash)
        self.sorted_node_hashes.sort()

    def get_node_for_key(self, key):
        key_hash = self.hash_function(key)

        # Find the first node hash >= key_hash
        # This can be done with binary search (bisect_left in Python)
        # For simplicity, let's use a linear scan for demonstration
        for node_hash in self.sorted_node_hashes:
            if node_hash >= key_hash:
                return self.nodes[node_hash]

        # If no such node is found, wrap around to the first node
        return self.nodes[self.sorted_node_hashes[0]]

# Example Usage:
# hasher = ConsistentHasher(['nodeA', 'nodeB', 'nodeC'])
# owner = hasher.get_node_for_key('my_data_key')

Data Structures for Efficient Lookup

While a linear scan works for a very small number of nodes, for larger clusters, you’d want more efficient lookup:

  • Sorted Array + Binary Search: This is the most common and efficient approach. It provides O(log N) lookup time, where N is the number of nodes.
  • Balanced Trees (e.g., Red-Black Tree, B-Tree): These can also maintain sorted order and offer O(log N) lookup, insertion, and deletion times, which is useful when nodes are frequently added or removed.
  • Skip Lists: Another data structure offering O(log N) average-case performance for sorted lookups.

The video emphasizes that for a small cluster (e.g., 5 nodes), even a linear search is perfectly acceptable. The choice of data structure depends on the scale and frequency of topology changes.

”Four Lines of Code” - The Simplicity

The claim that consistent hashing is “four lines of code” refers to the core lookup logic once the sorted array of node hashes is established. Finding the first element greater than or equal to a value in a sorted array is a fundamental programming task, often solved with a simple loop or a binary search function call.

Advanced Implementations (Brief Mention)

While the basic sorted array approach is highly effective, more sophisticated algorithms exist for specific use cases or performance optimizations:

  • Jump Consistent Hash (Google): A very fast, minimal-memory consistent hash function that doesn’t require storing node hashes in a data structure.
  • Rendezvous Hashing (HRW Hashing): An alternative that doesn’t use a ring, but rather calculates a “score” for each node for a given key, and the node with the highest score wins.
  • Maglev Hashing (Google): Part of Google’s Maglev paper, designed for high-performance load balancing.

These advanced methods build upon the core principles but are not necessary for understanding or implementing basic consistent hashing.

Key Takeaways and Pragmatic Advice

  1. Think Implementation: Always consider how an algorithm would be implemented. This clarifies its complexity, resource requirements, and true utility.
  2. Algorithm, Not Service: Consistent Hashing is a lightweight algorithm that runs wherever the topology is known (e.g., load balancer, API server, proxy) to route requests or determine data ownership.
  3. Scale Matters: For small clusters, a simple linear scan might be sufficient. Don’t over-engineer with complex data structures if not needed.
  4. Not Always a Perfect Fit: While excellent for minimizing ownership changes, consistent hashing doesn’t magically handle data migration. If data needs to be physically moved when ownership changes, that remains a separate, complex problem that needs careful consideration.
  5. Avoid Marketing Gimmicks: Don’t fall for the idea that it’s a “magical solution” that works everywhere. Apply critical thinking and understand its trade-offs and specific applicability.

By understanding consistent hashing from these first principles, you gain a powerful tool for designing scalable and resilient distributed systems.

Arpit Bhayani

Principal Engineer II at Razorpay - building Agent Studio, Ex-staff engg at GCP Memorystore & Dataproc, Creator of DiceDB, ex-Amazon Fast Data, ex-Director of Engg. SRE and Data Engineering at Unacademy. I spark engineering curiosity through my no-fluff engineering videos on YouTube and my courses