system-design · beginner
Load Balancing — Algorithms and Layers
The Central Question
Consider a web application whose domain api.checkoutlab.com resolves to a single IP address 203.0.113.10. If 50,000 users attempt to check out simultaneously, all 50,000 TCP connections concentrate on that single server. The CPU hits 100%, memory exhausts, connection queues fill, and the server crashes. The single IP address becomes a Single Point of Failure (SPOF).
To scale horizontally, an application must distribute incoming traffic across multiple redundant backend instances.
A load balancer is a specialized network component that acts as a reverse proxy, accepting client traffic at a single public entry point and distributing work across a pool of backend servers based on active health status and load algorithms.
This lesson answers one central question: How should incoming client connections and HTTP requests be distributed across a pool of healthy backend instances to maximize throughput, minimize latency, and maintain high availability?
The Reverse Proxy Architecture
A load balancer operates as a Reverse Proxy. Unlike a forward proxy (which hides client IP addresses when browsing out to the internet), a reverse proxy sits in front of backend servers to hide internal server infrastructure from public clients.
flowchart LR
subgraph Public Internet
C1[Client Browser A]
C2[Client Browser B]
end
subgraph Public Edge
LB[Load Balancer 203.0.113.10]
end
subgraph Private Network Tier
App1[App Server 172.16.1.10]
App2[App Server 172.16.1.11]
App3[App Server 172.16.1.12]
end
C1 -->|1. HTTP Request| LB
C2 -->|1. HTTP Request| LB
LB -->|2a. Forward| App1
LB -->|2b. Forward| App2
LB -.->|2c. Health Failed| App3
Figure 1: The reverse proxy architecture distributing incoming edge requests to internal private app nodes.
Traffic Routing Flow
- Public Client Connection: The client initiates a TCP handshake with the load balancer's public IP address (
203.0.113.10) on port443. - Backend Selection: The load balancer evaluates its target pool, filters out unhealthy instances, and applies a routing algorithm to select an active backend instance (e.g.
172.16.1.10). - Internal Forwarding: The load balancer forwards the request to the internal private IP address of the chosen backend server.
- Response Relay: The backend processes the request and sends the response back to the load balancer, which relays it to the public client.
Layer 4 (Transport) vs. Layer 7 (Application) Load Balancing
Load balancers operate at different OSI network stack layers, determining how deeply they inspect network packets.
flowchart TB
subgraph Layer 4: Transport-Level Balancing
L4[L4 Balancer] -->|Inspects IP:Port & TCP Flags| L4Route[Forward TCP Stream to Backend]
end
subgraph Layer 7: Application-Level Balancing
L7[L7 Balancer] -->|Decrypts TLS & Parses HTTP Headers| PathRoute{Inspect URL Path}
PathRoute -->|/checkout| Pool1[Payment App Pool]
PathRoute -->|/static| Pool2[Static CDN Origin Pool]
end
Figure 2: Comparing Layer 4 transport stream forwarding against Layer 7 HTTP content inspection.
1. Layer 4 Load Balancing (Transport Layer)
Layer 4 load balancers operate at the TCP/UDP transport layer. They inspect packet IP addresses and TCP port numbers without opening or parsing the application payload.- Mechanism: The balancer forwards raw TCP packets between the client and the backend server.
- Advantages: Extremely high throughput, low CPU overhead, and capability to balance non-HTTP TCP traffic (e.g. PostgreSQL, Redis, gRPC).
- Disadvantages: Cannot inspect HTTP headers, cookies, or URL paths; cannot perform content-based routing.
- Examples: AWS Network Load Balancer (NLB), HAProxy in TCP mode.
2. Layer 7 Load Balancing (Application Layer)
Layer 7 load balancers operate at the application layer. They terminate the client TCP connection, decrypt TLS/HTTPS encryption, and parse the full HTTP request (headers, cookies, URL paths, HTTP methods).- Mechanism: The balancer acts as an HTTP proxy, making routing decisions based on HTTP content.
- Advantages: Advanced path-based routing (
/api/checkoutvs/static/images), HTTP header manipulation (X-Forwarded-For), and cookie-based sticky sessions. - Disadvantages: Higher CPU consumption per request due to TLS decryption and HTTP parsing.
- Examples: Nginx, AWS Application Load Balancer (ALB), Envoy Proxy.
Routing Algorithms: How Balancers Select Backends
When a load balancer receives a request, it uses a deterministic algorithm to select an active backend instance from the target pool:
flowchart TD
Req[Incoming Client Request] --> Alg{Select Routing Algorithm}
Alg -->|Round-Robin| RR[Cyclic Target: Server 1 -> Server 2 -> Server 3]
Alg -->|Least Connections| LC[Least Busy Target: Server with Fewest Active TCP Sockets]
Alg -->|IP / Consistent Hash| Hash[Hash Ring Target: Hash Client IP to Fixed Server]
Figure 3: Overview of common load balancer target selection algorithms.
1. Round-Robin & Weighted Round-Robin
- Round-Robin: Rotates requests sequentially across the target pool ($S_1 \rightarrow S_2 \rightarrow S_3 \rightarrow S_1$).
- Weighted Round-Robin: Assigns static weights to instances based on hardware capacity. A server with weight
3receives three times as many requests as a server with weight1.
2. Least Connections
The load balancer tracks the exact count of active, open TCP connections on each backend server and routes new requests to the server with the fewest active connections.- Best For: Long-lived connections (WebSockets, database connection pools, file uploads) where request execution durations vary significantly.
3. IP Hash & Consistent Hashing
- IP Hash: Computes a hash of the client's source IP address (
hash(client_ip) % N) to map a specific user IP to the same backend server. - Consistent Hashing: Maps client keys and backend servers onto a logical $360^\circ$ hash ring. When backend nodes are added or removed, only a small fraction of keys are re-mapped ($1/N$), preventing global cache invalidation.
| Algorithm | CPU Overhead | Handles Unequal Request Workloads? | Preserves Client Affinity? |
|---|---|---|---|
| Round-Robin | Ultra-Low | No | No |
| Weighted Round-Robin | Low | Partially (via static weight) | No |
| Least Connections | Moderate | Yes | No |
| Consistent Hashing | Moderate | Yes | Yes (by hash key) |
Active Health Probes, Flapping, and Connection Draining
A load balancer is only as effective as its ability to detect and remove unhealthy backends.
stateDiagram-v2
[*] --> Healthy
Healthy --> Unhealthy : 2 Consecutive Failed Health Probes (6s)
note right of Healthy
Instance receives live traffic.
LB sends GET /healthz every 3s.
end note
Unhealthy --> Draining : Failure Detected
note right of Unhealthy
Removed from active routing table.
Zero new client requests sent.
end note
Draining --> Healthy : 3 Consecutive Successful Probes
note right of Draining
Existing TCP connections drain.
Wait for connection_draining_timeout (30s).
end note
Figure 4: State machine governing backend health checks and connection draining.
1. Active Health Checking
The load balancer continuously issues automated health probes to every registered instance:- Probe Target:
GET /healthzon HTTP port8080. - Interval: Every 3 seconds.
- Unhealthy Threshold: 2 consecutive failed responses (e.g. HTTP
500or timeout $> 1,000\text{ms}$). - Recovery Threshold: 3 consecutive successful HTTP
200 OKresponses before re-entering the pool.
2. Flapping Prevention
If an instance experiences memory pressure, it may pass one health check, fail the next, and pass the third. This rapid switching in and out of the pool is **flapping**. Load balancers prevent flapping by requiring multiple consecutive successful probes before re-adding an instance to the active pool.3. Connection Draining (Graceful Deregistration)
When an instance is marked unhealthy or targeted for auto-scale shutdown, the load balancer executes **Connection Draining**:- It stops sending new client requests to the instance immediately.
- It keeps existing active TCP connections open for a specified timeout (e.g. 30 seconds) to allow in-flight requests to complete cleanly.
- Once in-flight requests finish or the timeout expires, the socket is closed.
TLS Termination Models
Because Layer 7 load balancing requires reading HTTP content, load balancers manage Transport Layer Security (TLS/HTTPS) encryption using three deployment models:
flowchart LR
subgraph Model 1: TLS Termination at Edge
Client1[Client Browser] -->|HTTPS Encrypted| LB1[Load Balancer]
LB1 -->|Un-encrypted HTTP| App1[Private App Server]
end
subgraph Model 2: End-to-End mTLS Re-Encryption
Client2[Client Browser] -->|HTTPS Encrypted| LB2[Load Balancer]
LB2 -->|Internal HTTPS mTLS| App2[Private App Server]
end
Figure 5: Comparing TLS edge termination against internal mTLS re-encryption.
1. TLS Termination (Offloading)
The client establishes an encrypted HTTPS connection with the load balancer. The load balancer decrypts the traffic, inspects the HTTP headers, and forwards plain HTTP traffic to private application servers over a secure VPC network.- Benefit: Centralizes SSL/TLS certificate management on the load balancer; reduces application server CPU load by offloading cryptographic handshakes.
- TLS Pass-Through (Layer 4):
- End-to-End Re-Encryption (mTLS):
Sticky Sessions (Session Affinity) vs. Stateless Design
When legacy applications store user session data in server local memory rather than a centralized Redis cache, the load balancer must use Sticky Sessions (Session Affinity).
flowchart TB
subgraph Sticky Session Pinning
ClientA[Client A] -->|Cookie: LB_STICKY=NODE_1| LB[Load Balancer]
LB -->|PINNED| Node1[App Node 1]
ClientB[Client B] -->|Cookie: LB_STICKY=NODE_2| LB
LB -->|PINNED| Node2[App Node 2]
end
Figure 6: Cookie-based sticky session pinning tying specific clients to physical backend nodes.
How Sticky Sessions Work
The load balancer injects a HTTP cookie (`LB_STICKY=NODE_1`) into the client's first response. On subsequent requests, the client transmits this cookie, forcing the load balancer to route the user to `Node 1`.Operational Pitfalls of Sticky Sessions
- Uneven Load Distribution: If a high-volume client is pinned to
Node 1, that node becomes overloaded while adjacent nodes sit idle. - Broken Failover: If
Node 1crashes, all users pinned toNode 1lose their session state and are forcibly logged out when routed toNode 2. - Horizontal Autoscaling Obstacle: Auto-scaling cannot decommission
Node 1cleanly without breaking active pinned users.
Complete Worked Example: Path-Based Routing for CheckoutLab
Let's design a Layer 7 load balancer architecture for the CheckoutLab e-commerce service.
Routing Specification
- Domain:
https://checkoutlab.com https://checkoutlab.com/api/checkout/*$\rightarrow$ Forward to Payment Target Group (High CPU, 8 Nodes).https://checkoutlab.com/api/catalog/*$\rightarrow$ Forward to Catalog Read Target Group (High RAM, 4 Nodes).https://checkoutlab.com/static/*$\rightarrow$ Forward to Static Asset Storage Pool.
Execution Sequence Under Active Outage
sequenceDiagram
autonumber
actor Client as User Browser
participant LB as L7 Load Balancer (Nginx / ALB)
participant Pay1 as Payment Node 1 (DEADLOCK)
participant Pay2 as Payment Node 2 (HEALTHY)
participant Stat as Static Asset Pool
Client->>LB: GET /static/logo.png
LB->>Stat: Route to Static Pool
Stat-->>Client: HTTP 200 OK (5ms)
Client->>LB: POST /api/checkout/pay
LB->>Pay1: Route to Payment Target Group (Least Connections)
Note over Pay1: Times out (Health Probe fails 2x)
Note over LB: LB marks Pay1 UNHEALTHY; triggers Connection Draining
LB->>Pay2: Automatic Retry Forward to Payment Node 2
Pay2-->>LB: HTTP 200 OK { orderId: 8812 }
LB-->>Client: HTTP 200 OK (Total Latency: 110ms)
Figure 7: Path-based routing and automated health check failover on an L7 load balancer.
Load Balancing vs. Related Network Traffic Management Concepts
| Component | Layer | Primary Function | Distinctive Characteristic |
|---|---|---|---|
| Load Balancer | Layer 4 / Layer 7 | Distributes traffic across instance pools within a cloud region based on health checks. | Performs continuous automated health checking and instance failover. |
| DNS Multi-A (Round-Robin DNS) | Application (DNS) | Returns multiple IP addresses for a single domain name. | Lacks active health checking; client DNS caching delays failover by TTL minutes. |
| API Gateway | Layer 7 | Extends L7 balancing with API authentication, rate limiting, and request transformation. | Provides application-level policy enforcement beyond pure traffic routing. |
| Content Delivery Network (CDN) | Edge Network | Caches static assets globally on edge PoPs close to users. | Serves content from cache to prevent requests from hitting origin load balancers. |
Failure Modes and Engineering Mitigations
| Failure Scenario | Root Cause | System Symptom | Detection Signal | Mitigation Strategy |
|---|---|---|---|---|
| 1. Shallow Health Probe False Success | Health check probes static /health text file while DB connection pool is dead. | Load balancer routes traffic to instances returning HTTP 500 errors on API routes. | High 5xx error rate on user endpoints while LB reports 100% target group health. | Implement deep readiness probes that execute database SELECT 1 queries and check connection pool depth. |
| 2. Sticky Session Hotspot Sieve | High-volume client pinned to a single node via sticky session cookies. | Single application node CPU hits 100% while adjacent nodes operate at 10% CPU. | Severe CPU imbalance across target group nodes. | Refactor application to use stateless JWT authentication or external Redis session storage. |
| 3. Load Balancer Hairpin Bottleneck | Internal microservices route calls out through public load balancer rather than internal VPC. | Latency doubles and public load balancer bandwidth costs explode. | High bandwidth usage on public load balancer interfaces. | Use internal Layer 4 load balancers or service discovery (e.g. Kubernetes ClusterIP / Envoy mesh) for internal east-west traffic. |
| 4. Cascading Target Group Overload | Target group size set to $N$ with zero capacity headroom; 1 instance dies. | Remaining $N-1$ instances receive excess traffic, crash sequentially from CPU overload. | Cascading sequence of target instances marked unhealthy within 60 seconds. | Maintain capacity headroom ($N+2$ provisioning) and enforce rate limiting at the API gateway during outages. |
What You Should Remember
- Load Balancers are Reverse Proxies: They sit in front of private instance pools, acting as a stable public entry point while instances scale or fail.
- Layer 4 vs Layer 7: Layer 4 balances fast at the TCP level; Layer 7 decrypts HTTP to enable path-based routing (
/apivs/static) and header inspection. - Match Algorithm to Workload: Use Round-Robin for uniform workloads; use Least Connections for variable request durations (WebSockets, long polling).
- Health checks must reflect readiness: Shallow health probes lead to black-hole routing. Probes must verify critical database and thread pool health.
- Prefer Stateless Tiers over Sticky Sessions: Sticky sessions cause uneven load distribution and break graceful failovers. Move session state to Redis.
Glossary of Terms
| Term | Definition |
|---|---|
| Load Balancer | A reverse proxy server that distributes incoming network traffic across a pool of healthy backends. |
| Reverse Proxy | An intermediate server that accepts edge client requests and forwards them to private internal servers. |
| Layer 4 (L4) | Transport-level load balancing operating strictly on IP addresses and TCP/UDP ports. |
| Layer 7 (L7) | Application-level load balancing inspecting HTTP headers, cookies, and URL paths. |
| Round-Robin | A routing algorithm that rotates requests sequentially across a list of target instances. |
| Least Connections | A routing algorithm that directs incoming requests to the instance with the fewest active TCP connections. |
| Consistent Hashing | A hashing algorithm mapping keys and nodes to a ring structure, minimizing key re-mapping during node scaling. |
| Connection Draining | The process of stopping new traffic to an instance while allowing existing active requests to complete gracefully. |
| TLS Termination | Decrypting TLS/HTTPS encryption at the load balancer to forward un-encrypted HTTP to internal app nodes. |
Practice Scenario and Self-Assessment
Architecture Scenario
You are designing traffic management for a multi-service platform:- Web Frontend (Static HTML/JS assets)
- Payment API (HTTP REST, short execution time)
- Live Chat API (Persistent WebSockets, long-lived connections)
- For each of the three services, recommend whether Layer 4 or Layer 7 load balancing is appropriate, and justify your choice.
- Select the optimal balancing algorithm (Round-Robin vs Least Connections vs IP Hash) for the Live Chat API and explain why.
Interactive Self-Assessment
Layer 7 (Application Layer)
Layer 4 (Transport Layer)
Layer 3 (Network Layer)
Layer 2 (Data Link Layer)
Least Connections tracks active open connections, preventing traffic imbalances when connection durations vary widely.
Round-Robin requires more CPU memory to compute than Least Connections.
Least Connections is the only algorithm that supports encrypted TLS sockets.
Least Connections automatically bypasses database locks during WebSocket handshakes.
What to Learn Next
- Scalability — Vertical, Horizontal, and Elastic Growth: Revisit horizontal compute tier expansion with load balancing in mind.
- Availability — Nines, Error Budgets, and Redundancy: Learn how load balancer health probes protect system availability targets.
- Single Point of Failure: Explore high-availability load balancer pairs (VRRP / floating IPs).
Track: Engineering Foundations
Previous: Leader Election — Picking One Coordinator
Next: Long Polling vs WebSockets — Realtime Over HTTP
By Shubham Jain