<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Balaji Yalla</title>
    <description>The latest articles on DEV Community by Balaji Yalla (@balaji_yalla).</description>
    <link>https://dev.to/balaji_yalla</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F2421686%2F5eb3db35-6c70-45dc-9262-dff46de24ad0.jpg</url>
      <title>DEV Community: Balaji Yalla</title>
      <link>https://dev.to/balaji_yalla</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/balaji_yalla"/>
    <language>en</language>
    <item>
      <title>System Design 002: Load Balancing Explained</title>
      <dc:creator>Balaji Yalla</dc:creator>
      <pubDate>Tue, 12 May 2026 15:31:30 +0000</pubDate>
      <link>https://dev.to/balaji_yalla/system-design-002-load-balancing-explained-i3</link>
      <guid>https://dev.to/balaji_yalla/system-design-002-load-balancing-explained-i3</guid>
      <description>&lt;h2&gt;
  
  
  Load Balancing
&lt;/h2&gt;

&lt;h2&gt;
  
  
  🧱 What Is It?
&lt;/h2&gt;

&lt;p&gt;A Load Balancer (LB) distributes incoming network traffic across multiple backend servers to ensure no single server is overwhelmed. It acts as the traffic cop sitting between clients and your backend servers.&lt;/p&gt;




&lt;h2&gt;
  
  
  🚀 Why Do You Need It?
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Scalability:&lt;/strong&gt; Distributes load horizontally so you can scale by adding more machines rather than buying one massive expensive server.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;High Availability (HA):&lt;/strong&gt; Automatically detects dead servers (via health checks) and redirects traffic to healthy ones.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Redundancy &amp;amp; Failover:&lt;/strong&gt; Prevents your system from having a Single Point of Failure (SPOF).&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  📂 L4 vs L7 Load Balancers (The Core Division)
&lt;/h2&gt;

&lt;p&gt;The names L4 and L7 come from the &lt;strong&gt;OSI Model&lt;/strong&gt; (Open Systems Interconnection). To understand how they differ, think of a physical mail package:&lt;/p&gt;

&lt;h3&gt;
  
  
  ✉️ L4 (Layer 4 - Transport Layer) — "The Mailman"
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;How it works:&lt;/strong&gt; An L4 load balancer only looks at the &lt;strong&gt;outside of the envelope&lt;/strong&gt;. It only reads the &lt;strong&gt;IP addresses&lt;/strong&gt; (Layer 3) and the &lt;strong&gt;Port numbers&lt;/strong&gt; (Layer 4, TCP/UDP). It does not open the payload.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Pros:&lt;/strong&gt; Blazing-fast speeds! Because it doesn't decrypt traffic or parse protocols, it just forwards raw data packets.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cons (Dumb):&lt;/strong&gt; It cannot make smart decisions based on content (e.g., it cannot look at a cookie or direct &lt;code&gt;/images&lt;/code&gt; to a separate server).&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  🚀 Real-World Applications Where L4 Makes Sense:
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;High-Throughput Raw Streaming (UDP/TCP):&lt;/strong&gt; Media streaming services (VoIP, Zoom, RTSP video feeds) where raw speed is critical, and there are no HTTP headers/cookies to read.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Multiplayer Online Gaming Servers:&lt;/strong&gt; Real-time games stream player coordinates using custom, lightweight TCP/UDP binary packets. An L4 balancer handles this easily, whereas an L7 HTTP-bound balancer would not understand the gaming binary protocol.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Database Read-Replica Routing:&lt;/strong&gt; Directing SQL/NoSQL database TCP connections (MySQL, Redis, PostgreSQL) across replica nodes. Database traffic has no HTTP headers, so it is routed purely on TCP port levels.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Edge Gateway (The Front Door):&lt;/strong&gt; Massive platforms (like Google or Netflix) put a super-fast L4 load balancer at the absolute front of their datacenter to absorb billions of requests and spread them across a fleet of smart L7 balancers.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  📂 L7 (Layer 7 - Application Layer) — "The Receptionist"
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;How it works:&lt;/strong&gt; An L7 load balancer &lt;strong&gt;opens the envelope and reads your letter&lt;/strong&gt;. It performs &lt;strong&gt;TLS Termination&lt;/strong&gt; (decrypts HTTPS) and parses the HTTP/HTTPS request to read cookies, headers, URL paths, and query parameters.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;What it can do:&lt;/strong&gt; It can make highly intelligent routing decisions:

&lt;ul&gt;
&lt;li&gt;&lt;em&gt;"If URL starts with &lt;code&gt;/api&lt;/code&gt;, send to API Cluster. If it starts with &lt;code&gt;/video&lt;/code&gt;, send to Video Cluster."&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;"If there is a cookie called &lt;code&gt;session_id&lt;/code&gt;, use **Consistent Hashing&lt;/em&gt;* to keep the user on the same server."*&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;strong&gt;Pros:&lt;/strong&gt; Extremely smart, highly precise, and handles content-aware routing.&lt;/li&gt;

&lt;li&gt;

&lt;strong&gt;Cons:&lt;/strong&gt; Slower than L4 because decrypting TLS and parsing strings requires more CPU overhead.&lt;/li&gt;

&lt;/ul&gt;

&lt;h4&gt;
  
  
  🚀 Real-World Applications Where L7 Makes Sense:
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;E-Commerce &amp;amp; SaaS User Logins (Sticky Sessions):&lt;/strong&gt; Shopping carts and login systems require users to stay "stuck" to the same server holding their temporary state. L7 uses &lt;strong&gt;Consistent Hashing on the Session Cookie&lt;/strong&gt; to achieve this.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Microservices &amp;amp; API Gateways (Path-Based Routing):&lt;/strong&gt; Routing client requests based on URL path. For example, a single domain &lt;code&gt;api.company.com&lt;/code&gt; needs to route &lt;code&gt;/payments&lt;/code&gt; to the Payments Microservice and &lt;code&gt;/auth&lt;/code&gt; to the Identity Microservice.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Header-Based Security &amp;amp; Optimization:&lt;/strong&gt; Routing users to specific backend pools based on their device (&lt;code&gt;User-Agent&lt;/code&gt; header) or geolocations (&lt;code&gt;Accept-Language&lt;/code&gt; header).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Canary Deployments &amp;amp; A/B Testing:&lt;/strong&gt; Routing 10% of users with an experimental cookie (&lt;code&gt;group=canary&lt;/code&gt;) to a new test server, and the other 90% to the stable production server.&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  ⚡ The TCP/IP Reality: Why No L5 or L6 Balancers?
&lt;/h2&gt;

&lt;p&gt;The theoretical &lt;strong&gt;OSI Model&lt;/strong&gt; has 7 layers, including Layer 5 (Session) and Layer 6 (Presentation). However, the real-world internet runs on the &lt;strong&gt;TCP/IP Model&lt;/strong&gt;. &lt;/p&gt;

&lt;p&gt;In the TCP/IP model, &lt;strong&gt;Layers 5, 6, and 7 are consolidated under a single layer: Layer 7 (Application).&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;THEORETICAL (OSI Model)         PRACTICAL (TCP/IP Model)
┌─────────────────────────┐     ┌─────────────────────────┐
│ Layer 7: Application    │ ──► │                         │
├─────────────────────────┤     │                         │
│ Layer 6: Presentation   │ ──► │  Layer 7: Application   │
├─────────────────────────┤     │                         │
│ Layer 5: Session        │ ──► │                         │
└─────────────────────────┘     └─────────────────────────┘
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Because of this consolidation, when an L7 load balancer decrypts SSL/TLS (Layer 6) or manages browser sessions/connections (Layer 5), it is executed within the same software process that parses HTTP (Layer 7). Thus, we refer to it simply as an &lt;strong&gt;L7 Load Balancer&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  ⚙️ Load Balancing Algorithms
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Algorithm&lt;/th&gt;
&lt;th&gt;How It Works&lt;/th&gt;
&lt;th&gt;Best For&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Round Robin&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Routes requests sequentially (&lt;code&gt;Server 1&lt;/code&gt; → &lt;code&gt;2&lt;/code&gt; → &lt;code&gt;3&lt;/code&gt; → &lt;code&gt;1&lt;/code&gt;).&lt;/td&gt;
&lt;td&gt;Stateless servers (simplest approach).&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Least Connections&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Routes to the server with the fewest active requests.&lt;/td&gt;
&lt;td&gt;Long-running queries, downloads, or video streaming.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Weighted Round Robin&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Sends more requests to beefier, higher-capacity servers.&lt;/td&gt;
&lt;td&gt;Mixed-capacity server environments.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Consistent Hashing&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Maps requests and servers clockwise onto a virtual ring.&lt;/td&gt;
&lt;td&gt;Stateful servers (Sticky Sessions) and distributed caches.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  🌀 Consistent Hashing for "Sticky Sessions"
&lt;/h2&gt;

&lt;p&gt;When servers are &lt;em&gt;stateful&lt;/em&gt; (e.g., they hold local user WebSocket connections or in-memory chat buffers), the load balancer must achieve &lt;strong&gt;Session Stickiness&lt;/strong&gt;—sending the same user to the same server.&lt;/p&gt;

&lt;h3&gt;
  
  
  🚨 The Modulo Hazard (Why Modulo Fails)
&lt;/h3&gt;

&lt;p&gt;If you hash user IPs using standard modulo:&lt;br&gt;
$$\text{Server ID} = \text{hash}(\text{user_ip}) \pmod N$$&lt;br&gt;
When a server crashes or you auto-scale (changing $N$ by just 1), the math changes. &lt;strong&gt;Nearly 90% of your users will suddenly get routed to the wrong server and logged out.&lt;/strong&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  🛡️ The Consistent Hashing Solution
&lt;/h3&gt;

&lt;p&gt;By mapping servers and client requests onto a circular virtual ring, adding or removing a server &lt;strong&gt;only affects a tiny fraction ($\approx 1/N$) of users&lt;/strong&gt;. The other 90% remain connected with their sessions completely unbroken!&lt;/p&gt;
&lt;h3&gt;
  
  
  ⚠️ The Corporate "NAT / Proxy" Problem (L4 vs L7 Hashing)
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;[!IMPORTANT]&lt;br&gt;
&lt;strong&gt;The Golden Law of Sticky Sessions:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;L4 Layer Limitation:&lt;/strong&gt; You &lt;strong&gt;cannot&lt;/strong&gt; get the information of a unique &lt;strong&gt;User UUID&lt;/strong&gt; or &lt;strong&gt;Session ID&lt;/strong&gt; at the L4 layer. These are only available at Layer 7 because they reside inside the HTTP headers/payload, which L4 cannot decrypt or read.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The 2000-Employee Hotspot Risk:&lt;/strong&gt; If you establish sticky sessions at Layer 4, you are forced to hash on the &lt;strong&gt;Client IP Address&lt;/strong&gt;. However, client IP addresses are not always unique! If 2,000 employees in a corporate office connect to your app, they will share the &lt;strong&gt;exact same network public IP (due to NAT)&lt;/strong&gt;. This causes the L4 load balancer to stick &lt;strong&gt;all 2,000 employees onto a single backend server&lt;/strong&gt;, overloading it instantly while other servers sit idle.&lt;/li&gt;
&lt;/ol&gt;
&lt;/blockquote&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;IP Hash at L4:&lt;/strong&gt; Fast and simple, but risks overloading servers if multiple users connect from shared corporate networks or public hotspots (the NAT/Proxy bottleneck).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cookie/UUID Hash at L7:&lt;/strong&gt; Opens the packet, decrypts TLS, extracts the unique &lt;strong&gt;Session Cookie&lt;/strong&gt; or &lt;strong&gt;User UUID&lt;/strong&gt;, and hashes on it. Even if 2,000 users connect from the same office IP, they will have 2,000 distinct session IDs—resulting in perfect, uniform load balancing across your cluster.&lt;/li&gt;
&lt;/ul&gt;


&lt;h2&gt;
  
  
  🏆 Architectural Case Studies: When to Choose L4 vs. L7
&lt;/h2&gt;
&lt;h3&gt;
  
  
  📰 Case Study A: The Stateless Public App (e.g., News Reading Apps / Wikipedia)
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;The Scenario:&lt;/strong&gt; You are building a static public consumption app like a news reading app or a public wiki. Every visitor reads the exact same articles, and there is no user login state or shopping cart.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The Architecture:&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;No Sticky Sessions Needed:&lt;/strong&gt; Because the app is 100% stateless, any server can answer any request at any millisecond.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;L4 is the Perfect Choice:&lt;/strong&gt; Since sticky sessions are not required, we put a blazing-fast &lt;strong&gt;L4 Load Balancer&lt;/strong&gt; in front running simple &lt;strong&gt;Round Robin&lt;/strong&gt; or &lt;strong&gt;Least Connections&lt;/strong&gt;. It is highly cost-effective, has minimal CPU requirements, and handles massive traffic surges effortlessly.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  🏢 Case Study B: The Internal Enterprise Network (Corporate Intranets / VPCs)
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;The Scenario:&lt;/strong&gt; You are building a stateful application (like an internal corporate chat tool) deployed strictly on an internal corporate intranet or secure Virtual Private Cloud (VPC).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The Architecture:&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Private IP Uniqueness:&lt;/strong&gt; Unlike the public internet, every corporate device inside an enterprise is assigned a unique, non-shared &lt;strong&gt;Private IP Address&lt;/strong&gt; by the internal DHCP server. There are no external NAT gateway collisions!&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;L4 IP-Based Hashing Wins:&lt;/strong&gt; Because IP addresses are guaranteed to be unique inside the private intranet, you can safely use &lt;strong&gt;L4 Consistent Hashing based on Client IP&lt;/strong&gt; to achieve sticky sessions. It gives you session stickiness at blazing-fast, hardware-level speeds with zero SSL decryption/TLS parsing overhead!&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  🛍️ Case Study C: The Public Consumer App (e.g., E-Commerce / Chat Apps)
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;The Scenario:&lt;/strong&gt; You are building a public stateful app (like a retail site or messaging client) exposed to a large consumer base on the open internet.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The Architecture:&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;NAT Bottlenecks:&lt;/strong&gt; Users connect from shared networks (public Wi-Fi, cellular towers, home routers) where thousands of users share a single public IP. Hashing on IP at L4 will cause severe server hotspots.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;L7 Cookie-Based Hashing is Mandatory:&lt;/strong&gt; To ensure session stickiness without overload, you must use an &lt;strong&gt;L7 Load Balancer&lt;/strong&gt; that decrypts the traffic and hashes on unique &lt;strong&gt;User UUIDs&lt;/strong&gt; or &lt;strong&gt;Session Cookies&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;


&lt;h2&gt;
  
  
  🎥 Deep Dive: How Zoom/Video Calls Load Balance (The Signaling vs. Media Split)
&lt;/h2&gt;

&lt;p&gt;You just hit on a massive architectural challenge. In a video call platform (like Zoom, Google Meet, or Discord Voice), &lt;strong&gt;all participants in the same video room MUST connect to the exact same server instance&lt;/strong&gt; (called an &lt;em&gt;SFU - Selective Forwarding Unit&lt;/em&gt;) so the server can mix and forward their audio/video streams.&lt;/p&gt;

&lt;p&gt;However, raw video streams are incredibly heavy. If you tried to route gigabytes of encrypted video traffic through a single smart L7 HTTP load balancer to read a "Room UUID," &lt;strong&gt;the L7 load balancer's CPU would instantly melt from the decryption overhead.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;To solve this, real-world platforms use a brilliant architectural pattern called &lt;strong&gt;The Signaling vs. Media Plane Split (Two-Tier Routing)&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; 1. Join Room 123 (HTTP)      ┌───────────────────┐      3. Direct Media Server IP
 ────────────────────────────►│ L7 Load Balancer  ├──────────────────────────────────┐
                              └─────────┬─────────┘                                  │
                                        │ 2. Route                                   ▼
                              ┌─────────▼─────────┐                       ┌─────────────────────┐
                              │ Signaling Server  │                       │    Zoom Client      │
                              │ (Room Orchestrator│                       └──────────┬──────────┘
                              │   finds Server B) │                                  │
                              └───────────────────┘                                  │ 4. Direct Stream
                                                                                     │    (UDP IP:Port)
                                                                                     ▼
                              ┌───────────────────┐                       ┌─────────────────────┐
                              │  Media Server A   │                       │   Media Server B    │
                              │ (Room 456 Active) │                       │  (Room 123 Active)  │
                              └───────────────────┘                       └─────────────────────┘
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Tier 1: The Signaling Plane (L7 HTTP/WebSockets) — "The Booking Agent"
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;When you click "Join Room &lt;code&gt;123&lt;/code&gt;", your client does &lt;strong&gt;not&lt;/strong&gt; send video yet. It first sends a tiny, lightweight HTTP request over the &lt;strong&gt;L7 Load Balancer&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Because this is L7, the load balancer parses the payload and sends it to a &lt;strong&gt;Room Orchestrator Service&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;The Orchestrator looks at its database and says: &lt;em&gt;"Room &lt;code&gt;123&lt;/code&gt; is currently hosted on **Media Server B&lt;/em&gt;* (IP: &lt;code&gt;54.12.34.56&lt;/code&gt;, Port: &lt;code&gt;50005&lt;/code&gt;)."*&lt;/li&gt;
&lt;li&gt;The Signaling Server replies to your client: &lt;em&gt;"Welcome to Room 123! Go stream your video directly to IP &lt;code&gt;54.12.34.56&lt;/code&gt; on Port &lt;code&gt;50005&lt;/code&gt;!"&lt;/em&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Tier 2: The Media Plane (L4 UDP) — "The Direct Highway"
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Now, your Zoom client opens a raw &lt;strong&gt;UDP socket&lt;/strong&gt; connection directly to &lt;code&gt;54.12.34.56:50005&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;It bypasses the L7 HTTP load balancers entirely!&lt;/li&gt;
&lt;li&gt;The raw, heavy video packets are routed directly at &lt;strong&gt;Layer 4 (Transport/IP level)&lt;/strong&gt; straight to that dedicated media server.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  🌟 Why this is so brilliant:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Zero L7 CPU Overhead for Video:&lt;/strong&gt; Your expensive L7 load balancers only handle the lightweight "handshakes" (signaling). They never touch a single frame of the heavy video data.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Perfect Stickiness Without Packet Reading:&lt;/strong&gt; You get perfect room-level stickiness because the client was &lt;em&gt;explicitly told&lt;/em&gt; the exact IP address of the target server during the handshake phase!&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  💡 Interview Tips &amp;amp; Talking Points
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Never assume stateless:&lt;/strong&gt; If an interviewer asks you to scale a WebSocket-based chat app, immediately mention: &lt;em&gt;"Since connections are stateful, we will use an L7 load balancer with Consistent Hashing on the User UUID to maintain sticky sessions."&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Mention NAT Limitation:&lt;/strong&gt; When asked about using IP Hash for routing, bring up the &lt;strong&gt;Corporate NAT/Proxy problem&lt;/strong&gt;—it proves you understand real-world network traffic.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Default to L7 for API Gateways:&lt;/strong&gt; In microservices, put an L7 load balancer (like Nginx/Envoy) at the front to handle path-based routing (&lt;code&gt;/api/v1/users&lt;/code&gt; $\to$ User Service).&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  📚 Study Resources
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Gaurav Sen:&lt;/strong&gt; "Load Balancing" — Excellent coverage of L4 vs L7.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Gaurav Sen:&lt;/strong&gt; "Consistent Hashing" — Critical video to watch.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;ByteByteGo:&lt;/strong&gt; "Load Balancer" — High-quality animated visual guide.&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>loadbalancing</category>
      <category>systemdesign</category>
      <category>architecture</category>
      <category>l4vsl7</category>
    </item>
    <item>
      <title>System Design 001: Consistent Hashing Explained</title>
      <dc:creator>Balaji Yalla</dc:creator>
      <pubDate>Tue, 12 May 2026 14:36:46 +0000</pubDate>
      <link>https://dev.to/balaji_yalla/system-design-101-consistent-hashing-explained-1d4m</link>
      <guid>https://dev.to/balaji_yalla/system-design-101-consistent-hashing-explained-1d4m</guid>
      <description>&lt;h2&gt;
  
  
  Consistent Hashing
&lt;/h2&gt;

&lt;h2&gt;
  
  
  What Is It?
&lt;/h2&gt;

&lt;p&gt;Consistent Hashing is a distributed hashing scheme that operates independently of the number of servers in a cluster. It ensures that when servers are added or removed, only a minimal number of keys (roughly $K/N$, where $K$ is the number of keys and $N$ is the number of servers) are redistributed.&lt;/p&gt;




&lt;h2&gt;
  
  
  Understanding Hashing First 🔑
&lt;/h2&gt;

&lt;p&gt;Before diving into &lt;em&gt;consistent&lt;/em&gt; hashing, let's understand what &lt;strong&gt;hashing&lt;/strong&gt; is at its core.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. What is Hashing?
&lt;/h3&gt;

&lt;p&gt;Hashing is the process of taking an input of any size (a word, a file, a video, or an entire database row) and passing it through a mathematical formula (a &lt;strong&gt;Hash Function&lt;/strong&gt;) to produce a fixed-size string of characters or numbers, known as a &lt;strong&gt;Hash Value&lt;/strong&gt;, &lt;strong&gt;Hash Code&lt;/strong&gt;, or simply a &lt;strong&gt;Hash&lt;/strong&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  ┌───────────────┐        ┌───────────────┐        ┌──────────────┐
  │  Input Data   │ ─────► │ Hash Function │ ─────► │  Hash Value  │
  │ (Any length)  │        └───────────────┘        │ (Fixed size) │
  └───────────────┘                                 └──────────────┘
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Real-World Analogy: The Digital Fingerprint 👤
&lt;/h4&gt;

&lt;p&gt;Think of a hash as a &lt;strong&gt;digital fingerprint&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Unique Identification:&lt;/strong&gt; Two completely different files will have entirely different hashes, just as two different people have different fingerprints.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;One-Way Street:&lt;/strong&gt; You cannot reconstruct a person from their fingerprint. Similarly, you cannot reconstruct the original input from its hash.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Fixed Size:&lt;/strong&gt; Whether you hash the single letter &lt;code&gt;"a"&lt;/code&gt; or the entire &lt;em&gt;Wikipedia&lt;/em&gt; database, the resulting hash is always a compact, fixed-size code.&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  2. Key Properties of a Good Hash Function
&lt;/h3&gt;

&lt;p&gt;To be useful in software engineering and system design, a hash function must satisfy several key properties:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Property&lt;/th&gt;
&lt;th&gt;What it Means&lt;/th&gt;
&lt;th&gt;Why it Matters&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Deterministic&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;The same input &lt;em&gt;always&lt;/em&gt; yields the same hash output.&lt;/td&gt;
&lt;td&gt;If &lt;code&gt;hash("alice")&lt;/code&gt; was &lt;code&gt;9823&lt;/code&gt; today and &lt;code&gt;4102&lt;/code&gt; tomorrow, we could never locate Alice's data.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Fast Computation&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Computing the hash for any given input is highly efficient ($O(1)$).&lt;/td&gt;
&lt;td&gt;Systems perform millions of lookups per second; hashing cannot be a bottleneck.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Pre-image Resistance&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Given a hash, it is practically impossible to guess the original input.&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;Critical for security&lt;/strong&gt; (e.g., storing passwords).&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Collision Resistant&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Two different inputs should almost never produce the same hash.&lt;/td&gt;
&lt;td&gt;Prevents different items from overwriting each other in memory (&lt;strong&gt;Hash Collisions&lt;/strong&gt;).&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Avalanche Effect&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;A tiny change in the input completely and unpredictably changes the output hash.&lt;/td&gt;
&lt;td&gt;Changing &lt;code&gt;"password123"&lt;/code&gt; to &lt;code&gt;"Password123"&lt;/code&gt; should produce completely unrelated hashes.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h3&gt;
  
  
  3. Hashing in Action: Everyday Examples
&lt;/h3&gt;

&lt;p&gt;We use basic hashing in three main areas of software engineering:&lt;/p&gt;

&lt;h4&gt;
  
  
  A. Data Integrity (Checksums)
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Scenario:&lt;/strong&gt; You download a 5GB installer. How do you know the file wasn't corrupted or tampered with during the download?&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Solution:&lt;/strong&gt; The host publishes an &lt;strong&gt;MD5&lt;/strong&gt; or &lt;strong&gt;SHA-256&lt;/strong&gt; checksum (hash). Once downloaded, you run your file through the same hash function. If your hash matches their checksum, the file is $100\%$ intact.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  B. Security (Password Hashing)
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Scenario:&lt;/strong&gt; Databases should &lt;em&gt;never&lt;/em&gt; store plain-text passwords. If a hacker breaches the database, they get everything.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Solution:&lt;/strong&gt; When you sign up, the system hashes your password (using slow, secure algorithms like bcrypt or Argon2) and stores only the hash. When you log in, the system hashes your entered password and compares it to the stored hash.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  C. In-Memory Search (Hash Maps / Hash Tables)
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Scenario:&lt;/strong&gt; You have a dictionary of 1,000,000 words. How do you look up a definition in $O(1)$ time?&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Solution:&lt;/strong&gt;

&lt;ol&gt;
&lt;li&gt;Store definitions in an array.&lt;/li&gt;
&lt;li&gt;To store &lt;code&gt;"apple"&lt;/code&gt;, compute &lt;code&gt;index = hash("apple") % array_length&lt;/code&gt;. Store the definition at &lt;code&gt;array[index]&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;To look up &lt;code&gt;"apple"&lt;/code&gt;, compute the same index and jump directly to it in memory.&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h5&gt;
  
  
  Wait... Is the index guaranteed to be unique? (The Truth About Collisions 💥)
&lt;/h5&gt;

&lt;p&gt;No! It is mathematically impossible for indices to always be unique due to the &lt;strong&gt;Pigeonhole Principle&lt;/strong&gt; (e.g., if you have 10 slots and 11 keys, at least one slot must be shared). When two different keys map to the exact same index, it is called a &lt;strong&gt;Hash Collision&lt;/strong&gt;.&lt;/p&gt;

&lt;h5&gt;
  
  
  How are Collisions Handled and Stored in Memory? (The Node Chain ⛓️)
&lt;/h5&gt;

&lt;p&gt;Under the hood, instead of storing the raw value directly in the array slot, the array contains &lt;strong&gt;pointers/references to Node objects&lt;/strong&gt;. Each Node is a small package containing:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;hash_value&lt;/code&gt; (the integer hash code, saved to prevent recomputation)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;key&lt;/code&gt; (e.g., &lt;code&gt;"apple"&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;value&lt;/code&gt; (e.g., &lt;code&gt;"red fruit"&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;next&lt;/code&gt; (pointer to the &lt;em&gt;next&lt;/em&gt; Node in the chain, or &lt;code&gt;null&lt;/code&gt;)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;When &lt;code&gt;"apple"&lt;/code&gt; and &lt;code&gt;"banana"&lt;/code&gt; both hash to index &lt;code&gt;3&lt;/code&gt;, the system creates a linked chain:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;array:
[0] ──► null
[1] ──► null
[2] ──► null
[3] ──► [ hash: 103 | key: "apple" | value: "red fruit" | next: ────┐ ]
[4] ──► null                                                         │
                                                                     ▼ (linked chain)
                                        [ hash: 243 | key: "banana" | value: "yellow fruit" | next: null ]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h5&gt;
  
  
  How Lookup Works with Collisions:
&lt;/h5&gt;

&lt;p&gt;When you perform &lt;code&gt;map.get("banana")&lt;/code&gt;:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Direct Jump:&lt;/strong&gt; The map calculates &lt;code&gt;index = hash("banana") % 10&lt;/code&gt; $\to$ &lt;code&gt;3&lt;/code&gt;, jumping instantly to &lt;code&gt;array[3]&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Sequential Search:&lt;/strong&gt; It scans the chain at index &lt;code&gt;3&lt;/code&gt;. It checks if the current node's &lt;code&gt;key == "banana"&lt;/code&gt;. The first node is &lt;code&gt;"apple"&lt;/code&gt; (no match), so it follows the &lt;code&gt;next&lt;/code&gt; pointer to find the next node: &lt;code&gt;"banana"&lt;/code&gt; (match!). It returns &lt;code&gt;"yellow fruit"&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;




&lt;h3&gt;
  
  
  4. How Long is a Hash Value?
&lt;/h3&gt;

&lt;p&gt;The length of a hash value is &lt;strong&gt;completely independent of the input size&lt;/strong&gt; and is &lt;strong&gt;strictly determined by the specific algorithm&lt;/strong&gt; you choose. Depending on the use case, hashes are typically represented as either &lt;strong&gt;integers&lt;/strong&gt; or &lt;strong&gt;hexadecimal strings&lt;/strong&gt; (0-9, a-f).&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Use Case&lt;/th&gt;
&lt;th&gt;Common Algorithm&lt;/th&gt;
&lt;th&gt;Hash Bit Size&lt;/th&gt;
&lt;th&gt;Output Representation&lt;/th&gt;
&lt;th&gt;Real-World Example&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;strong&gt;System Design / Routing&lt;/strong&gt; &lt;br&gt;&lt;em&gt;(Ultra-fast, non-cryptographic)&lt;/em&gt;
&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;MurmurHash3&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;32-bit&lt;/strong&gt; or &lt;strong&gt;128-bit&lt;/strong&gt;
&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;Integer:&lt;/strong&gt; Up to $2^{32}-1$ (approx. 4.2B) &lt;br&gt;&lt;strong&gt;Hex:&lt;/strong&gt; 32-character string&lt;/td&gt;
&lt;td&gt;Used by &lt;strong&gt;Apache Cassandra&lt;/strong&gt; and &lt;strong&gt;DynamoDB&lt;/strong&gt; to distribute partition keys.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;strong&gt;Data Integrity Check&lt;/strong&gt; &lt;br&gt;&lt;em&gt;(Fast, simple checksums)&lt;/em&gt;
&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;MD5&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;128-bit&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;Hex:&lt;/strong&gt; 32-character string &lt;br&gt;&lt;em&gt;(e.g., &lt;code&gt;1f3870be274f6c49b3e31a0c6728957f&lt;/code&gt;)&lt;/em&gt;
&lt;/td&gt;
&lt;td&gt;File download checksums.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;strong&gt;Security &amp;amp; Cryptography&lt;/strong&gt; &lt;br&gt;&lt;em&gt;(Secure, slower, hard to crack)&lt;/em&gt;
&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;SHA-256&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;256-bit&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;Hex:&lt;/strong&gt; 64-character string &lt;br&gt;&lt;em&gt;(e.g., &lt;code&gt;3a7bd3e239ee2f28...&lt;/code&gt;)&lt;/em&gt;
&lt;/td&gt;
&lt;td&gt;Used in &lt;strong&gt;Git commit hashes&lt;/strong&gt;, SSL/TLS certificates, and Bitcoin.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h3&gt;
  
  
  5. Learning Tip: Treat Hashing as a "Black Box" in System Design 📦
&lt;/h3&gt;

&lt;p&gt;When studying system design or preparing for interviews, you should treat the mathematical internals of hash functions as a &lt;strong&gt;complete black box&lt;/strong&gt;. &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;[!NOTE]&lt;br&gt;
Interviewers do not care about polynomial divisions, bit-shifting logic, or prime-number multiplication sequences. &lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Instead, you only need to understand the &lt;strong&gt;properties and trade-offs&lt;/strong&gt; of the box:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Non-Cryptographic vs. Cryptographic:&lt;/strong&gt; Use cryptographic hashes (like SHA-256) when security is paramount (slower, resource-heavy). Use non-cryptographic hashes (like MurmurHash) when raw speed and throughput are needed (routing, database indexing, load balancing).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Uniformity:&lt;/strong&gt; You must assume the black box distributes inputs &lt;strong&gt;perfectly uniformly&lt;/strong&gt; across the output space. This is key because uniform distribution guarantees that your servers get equal traffic and you don't end up with overloaded "hotspots."&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Determinism:&lt;/strong&gt; Given input $X$, the output is &lt;em&gt;always&lt;/em&gt; $Y$. If it weren't, you would store a user's data on Server A today and never be able to locate it tomorrow.&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  6. Transitioning to System Design
&lt;/h3&gt;

&lt;p&gt;In a single-machine application, a &lt;strong&gt;Hash Map&lt;/strong&gt; works beautifully because the array of buckets resides in a single system's memory.&lt;/p&gt;

&lt;p&gt;But what happens when your data is too big for one machine, and you need to distribute it across &lt;strong&gt;multiple servers&lt;/strong&gt;? This is where distributed hashing and &lt;strong&gt;Consistent Hashing&lt;/strong&gt; come into play!&lt;/p&gt;




&lt;h2&gt;
  
  
  Why Do You Need It?
&lt;/h2&gt;

&lt;h3&gt;
  
  
  The Traditional Modulo Hashing Problem 🌀
&lt;/h3&gt;

&lt;p&gt;In standard load balancing or database sharding, we use a simple modulo-based hashing algorithm to distribute keys across $N$ servers:&lt;br&gt;
$$\text{Server ID} = \text{hash}(\text{key}) \pmod N$$&lt;/p&gt;

&lt;p&gt;If you have 5 servers ($N=5$):&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;hash("user_A") = 100&lt;/code&gt; $\to$ &lt;code&gt;100 % 5 = 0&lt;/code&gt; (Server 0)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;hash("user_B") = 101&lt;/code&gt; $\to$ &lt;code&gt;101 % 5 = 1&lt;/code&gt; (Server 1)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you add a 6th server ($N=6$):&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;hash("user_A") = 100&lt;/code&gt; $\to$ &lt;code&gt;100 % 6 = 4&lt;/code&gt; (Was Server 0, now &lt;strong&gt;Server 4&lt;/strong&gt; ❌)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;hash("user_B") = 101&lt;/code&gt; $\to$ &lt;code&gt;101 % 6 = 5&lt;/code&gt; (Was Server 1, now &lt;strong&gt;Server 5&lt;/strong&gt; ❌)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This change causes a &lt;strong&gt;Rehash Storm&lt;/strong&gt;:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;In Cache Clusters (Redis/Memcached):&lt;/strong&gt; Nearly $80\% - 90\%$ of keys suddenly map to different servers, causing a massive cache miss spike that floods the primary database (&lt;strong&gt;Cache Stampede&lt;/strong&gt;).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;In Database Shards:&lt;/strong&gt; Moving nearly all data to new servers requires intensive network bandwidth and cluster-wide locks.&lt;/li&gt;
&lt;/ol&gt;


&lt;h2&gt;
  
  
  The Consistent Hashing Algorithm
&lt;/h2&gt;

&lt;p&gt;Consistent hashing solves the rehash storm by mapping both &lt;strong&gt;Servers (Nodes)&lt;/strong&gt; and &lt;strong&gt;Keys&lt;/strong&gt; onto a circular virtual ring called the &lt;strong&gt;Hash Ring&lt;/strong&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;                         0 / 2^32 - 1
                        . - ~ - .
                    '               '  ◄─── Server A (at 100,000)
                  /                   \
                 /     Key 1           \
                |     (hash: 150,000)   |  ───► Maps Clockwise to Server B
                |                       |
                 \                     /
                  \                   /
                    .               .  ◄─── Server B (at 2,000,000)
                        ' - _ _ _ .
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  1. The Hash Ring
&lt;/h3&gt;

&lt;p&gt;The hash space is represented as a circular ring from $0$ to $2^{32} - 1$ (the maximum value of a 32-bit integer).&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Placing Servers on the Ring
&lt;/h3&gt;

&lt;p&gt;Each physical server is hashed using its IP address or Hostname and placed on a specific coordinate on the ring:&lt;br&gt;
$$\text{Server Position} = \text{hash}(\text{"192.168.1.100"}) \pmod{2^{32}}$$&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Placing Keys on the Ring
&lt;/h3&gt;

&lt;p&gt;Incoming keys are hashed using the same function and positioned on the same ring space:&lt;br&gt;
$$\text{Key Position} = \text{hash}(\text{"user-123"}) \pmod{2^{32}}$$&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Routing Keys to Servers (Clockwise Lookup)
&lt;/h3&gt;

&lt;p&gt;To locate the server for a specific key:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Locate the key's coordinate on the ring.&lt;/li&gt;
&lt;li&gt;Traverse the ring &lt;strong&gt;clockwise&lt;/strong&gt; until you encounter the first server node.&lt;/li&gt;
&lt;li&gt;Assign the key to that server.&lt;/li&gt;
&lt;li&gt;If a key's hash is larger than the highest server hash on the ring, it wraps around back to $0$ and lands on the first server.&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  How Scaling Works
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Adding a Server (Scale Up)
&lt;/h3&gt;

&lt;p&gt;Suppose we add a new server, &lt;strong&gt;Server D&lt;/strong&gt;, between Server A and Server B.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Affected Range:&lt;/strong&gt; Only the keys whose hashes fall in the range between Server A and Server D are shifted.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Redistribution:&lt;/strong&gt; These keys, which were previously owned by Server B, are now assigned to Server D.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Result:&lt;/strong&gt; Servers A and C are completely untouched. Only a tiny fraction ($\approx 1/N$) of total keys are migrated.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Removing a Server (Scale Down / Failure)
&lt;/h3&gt;

&lt;p&gt;Suppose &lt;strong&gt;Server B&lt;/strong&gt; crashes.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Affected Range:&lt;/strong&gt; Only keys that were assigned to Server B (hashes falling between Server A and Server B) are affected.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Redistribution:&lt;/strong&gt; These keys fall through clockwise and land on Server C.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Result:&lt;/strong&gt; No other keys in the cluster are affected or moved.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  The Hotspot Problem &amp;amp; Virtual Nodes (VNodes)
&lt;/h2&gt;

&lt;h3&gt;
  
  
  The Problem: Non-Uniform Distribution
&lt;/h3&gt;

&lt;p&gt;If servers are placed randomly on the ring, they might land very close to one another. &lt;br&gt;
For example, if Server A is at $10,000$, Server B at $20,000$, and Server C at $3,000,000$:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Server C has to handle keys with hashes from $20,000$ to $3,000,000$ (almost $99\%$ of the ring).&lt;/li&gt;
&lt;li&gt;This creates &lt;strong&gt;unbalanced segments&lt;/strong&gt; and &lt;strong&gt;hotspot servers&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  The Solution: Virtual Nodes (VNodes)
&lt;/h3&gt;

&lt;p&gt;Instead of mapping a physical server to a single coordinate, we map it to &lt;strong&gt;multiple virtual nodes (vnodes)&lt;/strong&gt; (e.g., 100 to 200 per physical server) scattered across the ring.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Physical Server A $\to$ &lt;code&gt;A#1&lt;/code&gt;, &lt;code&gt;A#2&lt;/code&gt;, ..., &lt;code&gt;A#200&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Physical Server B $\to$ &lt;code&gt;B#1&lt;/code&gt;, &lt;code&gt;B#2&lt;/code&gt;, ..., &lt;code&gt;B#200&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;   ---[ Ring Interleaving Layout ]---
   (0) ... A#1 ... B#2 ... C#1 ... A#2 ... B#1 ... C#2 ... (2^32-1)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Why VNodes are awesome:
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Balanced Distribution:&lt;/strong&gt; The larger number of points interleaves uniformly across the ring, keeping partition sizes equal.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Graceful Failover:&lt;/strong&gt; If Physical Server A fails, its virtual nodes (&lt;code&gt;A#1&lt;/code&gt;, &lt;code&gt;A#2&lt;/code&gt;, etc.) disappear. Because they were scattered, their keys are distributed uniformly to &lt;em&gt;various&lt;/em&gt; virtual nodes of &lt;em&gt;multiple&lt;/em&gt; other servers, instead of dumping all the load onto a single next-door physical neighbor.&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  🎯 Core Architectural Insights
&lt;/h2&gt;

&lt;p&gt;These two direct points perfectly summarize when and why we choose one hashing scheme over another:&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Static Clusters ──► Standard Modulo Hashing Wins 🏆
&lt;/h3&gt;

&lt;p&gt;If the number of servers in your cluster is &lt;strong&gt;completely static and guaranteed to never change&lt;/strong&gt; (no scaling, and failures are handled without cluster re-sharding), &lt;strong&gt;standard modulo hashing is superior to consistent hashing.&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Why:&lt;/strong&gt; It distributes the load perfectly uniformly, requires absolute minimum CPU overhead ($O(1)$ lookup), and does not require storing or searching a hash ring in memory.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  2. Dynamic Clusters ──► Consistent Hashing + VNodes Wins 🌀
&lt;/h3&gt;

&lt;p&gt;If your cluster size changes frequently (dynamic auto-scaling or frequent node crashes):&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Classic Consistent Hashing fails:&lt;/strong&gt; Placing each server at only one random point leaves massive uneven gaps on the ring, creating heavily overloaded "hotspot" servers.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Virtual Nodes (VNodes) are mandatory:&lt;/strong&gt; By mapping each physical machine to $100$ to $200$ virtual positions, we interleave the ring boundaries, guaranteeing nearly perfect load distribution and smooth, uniform load redistribution during scaling/failure events.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  🏢 Real-World Use Cases
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Amazon DynamoDB &amp;amp; Apache Cassandra:&lt;/strong&gt; Distribute records across database nodes.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Discord Gateways:&lt;/strong&gt; Direct WebSocket connections and chat channels to separate server nodes dynamically.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Akamai CDN:&lt;/strong&gt; Distribute web assets across global edge-caching networks uniformly to prevent overloading any edge server.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  💡 Interview Tips
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Don't jump to Consistent Hashing&lt;/strong&gt; unless scale modifications are a primary constraint. If the cluster size never changes, standard hashing is faster and simpler.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Mention Virtual Nodes&lt;/strong&gt; immediately when discussing Consistent Hashing. It shows you understand real-world systems rather than just the theoretical baseline.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Analyze Complexity:&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Lookup Time:&lt;/strong&gt; $O(\log(N \times V))$ where $N$ is servers and $V$ is vnodes.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Space Complexity:&lt;/strong&gt; $O(N \times V)$ to store the ring in memory.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  🌟 Summary: The Soul of Consistent Hashing
&lt;/h2&gt;

&lt;p&gt;If you need to summarize the entire essence of Consistent Hashing in one single sentence:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;"Consistent Hashing was created to achieve an even load distribution and an easy way to scale clusters dynamically without disrupting existing servers, ensuring that the same user load consistently routes to the same server."&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;It accomplishes this via three key architectural pillars:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Even Load (The Balance Pillar):&lt;/strong&gt; Uses Virtual Nodes (VNodes) to statistically guarantee that all servers get an equal share of traffic.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Easy Scaling (The Elasticity Pillar):&lt;/strong&gt; Guarantees that adding or removing a server only affects a minimal fraction ($\approx 1/N$) of keys, completely preventing cluster-wide "Rehash Storms."&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Consistent Mapping (The Determinism Pillar):&lt;/strong&gt; Ensures that a request for the same key always routes to the exact same server, keeping cache hit rates high and data lookups instant.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  YouTube Resources
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://www.youtube.com/watch?v=zaRkONvyGr8" rel="noopener noreferrer"&gt;Gaurav Sen: Consistent Hashing&lt;/a&gt; — Essential concept walkthrough.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.youtube.com/watch?v=UF9Iqmg94tk" rel="noopener noreferrer"&gt;ByteByteGo: Consistent Hashing Explained&lt;/a&gt; — Superb animations on the hash ring mechanics.&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>systemdesign</category>
      <category>hashing</category>
      <category>loadbalancing</category>
      <category>scaling</category>
    </item>
  </channel>
</rss>
