Chapter 19: Load Balancers

1. Why Load Balancing

Core problem: A single server has limited capacity (CPU, memory, network, connections). Load balancers distribute traffic across multiple servers for horizontal scaling, high availability, and single point of failure elimination.

graph LR A[Client] -->|Request| B[Single Server] B -->|Response| A style B fill:#f96,stroke:#333,stroke-width:4px C[Client] -->|Request| D[Load Balancer] D -->|Route| E[Server 1] D -->|Route| F[Server 2] D -->|Route| G[Server 3] E -->|Response| D F -->|Response| D G -->|Response| D D -->|Response| C style D fill:#9f6,stroke:#333,stroke-width:2px
Benefit Description Example
Horizontal Scaling Add more servers to handle increased load 10 servers @ 1000 RPS each = 10k RPS capacity
High Availability Server failure doesn't take down service If 1 of 10 servers fails, 90% capacity remains
Zero-Downtime Deploys Deploy to subset while others serve traffic Rolling deployment: update 2 servers at a time
Geographic Distribution Route users to nearest datacenter US users β†’ US DC, EU users β†’ EU DC
Health-Based Routing Avoid routing to unhealthy servers Remove server with high error rate from pool
Interview Tip: When asked "why use a load balancer?", mention both capacity (scaling) and availability (fault tolerance). Single server = single point of failure. Also mention operational flexibility: zero-downtime deploys, A/B testing, canary releases.

2. Layer 4 vs Layer 7 Load Balancing

Key distinction: L4 operates at transport layer (TCP/UDP), L7 operates at application layer (HTTP/gRPC). Different visibility, capabilities, and performance characteristics.

Aspect Layer 4 (Transport) Layer 7 (Application)
OSI Layer Transport (TCP/UDP) Application (HTTP/gRPC/WebSocket)
Visibility IP, port, TCP flags Headers, URL path, cookies, request body
Routing Decisions IP hash, connection count URL path, header, cookie, query param
Performance ~1M RPS, <1ms latency ~100k RPS, 1-5ms latency
SSL Termination No (passthrough) Yes (decrypt/inspect/re-encrypt)
Content-Based Routing No Yes (/api β†’ service A, /images β†’ service B)
Connection Handling Single TCP connection end-to-end Two connections (client↔LB, LB↔server)
Protocol Support Any TCP/UDP protocol HTTP/1.1, HTTP/2, HTTP/3, gRPC, WebSocket
Use Cases High throughput, non-HTTP protocols, SQL DBs Microservices, API gateways, HTTP routing
Examples AWS NLB, HAProxy (TCP mode), IPVS AWS ALB, Nginx, Envoy, HAProxy (HTTP mode)

Direct Server Return (DSR)

L4 optimization where response bypasses load balancer and goes directly from server to client. Reduces LB bandwidth (only ingress traffic passes through LB). Requires server to have LB's VIP on loopback interface.

sequenceDiagram participant C as Client participant L4 as L4 LB participant S as Server Note over C,S: Standard L4 (both directions through LB) C->>L4: SYN to VIP:443 L4->>S: SYN to Server:443 S->>L4: SYN-ACK L4->>C: SYN-ACK C->>L4: Request L4->>S: Request S->>L4: Response (large) L4->>C: Response (large) Note over C,S: DSR (response bypasses LB) C->>L4: SYN to VIP:443 L4->>S: SYN (DSR mode) S-->>C: SYN-ACK (direct) C->>L4: Request L4->>S: Request S-->>C: Response (direct, bypasses LB)

L4 vs L7 Architecture

graph TB subgraph "Layer 4 Load Balancer" C1[Client] -->|TCP SYN| L4[L4 LB] L4 -->|Inspect: IP, Port| L4 L4 -->|Forward TCP| S1[Server 1] L4 -->|Forward TCP| S2[Server 2] S1 -->|TCP Response| C1 S2 -->|TCP Response| C1 style L4 fill:#ff9 end subgraph "Layer 7 Load Balancer" C2[Client] -->|HTTPS Request| L7[L7 LB] L7 -->|Decrypt SSL| L7 L7 -->|Inspect: URL, Headers, Body| L7 L7 -->|Route by /api/users| S3[Users Service] L7 -->|Route by /api/orders| S4[Orders Service] S3 -->|HTTP Response| L7 S4 -->|HTTP Response| L7 L7 -->|Encrypt SSL| L7 L7 -->|HTTPS Response| C2 style L7 fill:#9ff end
Interview Tip: L4 vs L7 is a common question. Key points: L4 is faster (no SSL termination, no HTTP parsing) but less flexible (can't route by URL). L7 enables microservices routing (/users β†’ UserService) but adds latency. DSR is an L4 optimization for high-bandwidth scenarios.

3. Load Balancing Algorithms

Goal: Distribute load fairly and efficiently across backend servers. Different algorithms optimize for different goals: simplicity, fairness, statefulness, performance.

Algorithm How It Works Pros Cons Use Case
Round Robin Cycle through servers sequentially: 1β†’2β†’3β†’1 Simple, stateless, fair if requests equal cost Ignores server load/capacity, uneven if req cost varies Homogeneous servers, uniform request cost
Weighted Round Robin Assign weight to each server (2x weight = 2x traffic) Accounts for heterogeneous capacity Static weights, doesn't adapt to runtime load Mixed instance types (m5.large + m5.2xlarge)
Least Connections Route to server with fewest active connections Adapts to actual load, good for long-lived conns Requires state, doesn't account for request cost WebSockets, streaming, database connections
Weighted Least Connections Least connections + server weights Combines capacity awareness + runtime load More complex state tracking Heterogeneous servers with long-lived conns
IP Hash Hash client IP β†’ deterministic server Session affinity without cookies, simple Uneven load if few clients, sticky on server failure Sticky sessions for legacy apps
Consistent Hashing Hash space (0-2^32) with virtual nodes, minimal rebalancing Only K/N keys remap on server add/remove More complex, uneven load without virtual nodes Distributed caches (Memcached, Redis cluster)
Power of Two Choices Pick 2 random servers, choose one with fewer connections Near-optimal balance with O(1) cost, probabilistic fairness Requires connection state High-throughput L7 LBs (Envoy default)
Least Response Time Route to server with lowest avg response time Adapts to server performance degradation Requires tracking latency metrics, can cascade failures Heterogeneous backends with varying performance
Random Pick random server for each request Stateless, simple, no hotspots with many servers Short-term imbalance possible Stateless HTTP APIs with many backends

Algorithm Comparison

graph TD A[Choose Algorithm] --> B{Need session affinity?} B -->|Yes| C[IP Hash or Consistent Hash] B -->|No| D{Long-lived connections?} D -->|Yes| E[Least Connections] D -->|No| F{Heterogeneous servers?} F -->|Yes| G[Weighted Round Robin] F -->|No| H{High throughput?} H -->|Yes| I[Power of Two Choices] H -->|No| J[Round Robin]

Consistent Hashing Deep Dive

Maps keys and servers to a hash ring (0 to 2^32-1). Each key routes to the next server clockwise on the ring. When a server is added/removed, only ~1/N keys remap (vs 100% with naive hashing).

graph LR subgraph "Hash Ring" A[Server A
Hash: 100] --> B[Server B
Hash: 200] B --> C[Server C
Hash: 300] C --> A K1[Key 1
Hash: 150] -.->|Routes to| B K2[Key 2
Hash: 250] -.->|Routes to| C K3[Key 3
Hash: 50] -.->|Routes to| A end

Virtual nodes: Each physical server gets 100-500 virtual nodes on the ring to ensure even distribution. Without virtual nodes, servers could cluster and cause uneven load.

Interview Tip: When asked about algorithms, mention the tradeoff: simple (Round Robin) vs adaptive (Least Connections) vs sticky (IP Hash). Power of Two Choices is a great answer for "what does Envoy use?" Consistent Hashing is essential for caching layers but overkill for stateless APIs.

4. Health Checks

Purpose: Detect unhealthy servers and remove them from the load balancing pool. Prevent routing requests to failed/degraded instances.

Type How It Works Pros Cons Example
TCP Health Check Open TCP connection to port, close if successful Fast, low overhead, works for any TCP service Doesn't validate app logic, false positives Connect to port 8080, if SYN-ACK received β†’ healthy
HTTP Health Check GET /health, expect 200 OK within timeout Validates HTTP stack, can check dependencies Slower than TCP, requires HTTP endpoint GET /health returns 200 if DB reachable
gRPC Health Check Call grpc.health.v1.Health/Check service Standard for gRPC services, rich status info Requires gRPC support, more complex Check(service="myapp") β†’ SERVING/NOT_SERVING
Active Health Check LB periodically probes servers (every 5-30s) Proactive detection, configurable thresholds Extra load on servers, detection lag (5-30s) Every 10s, fail after 3 consecutive failures
Passive Health Check Monitor real request success/failure rates No extra load, immediate detection on traffic Requires traffic to detect, can miss issues If 5 consecutive 5xx errors β†’ mark unhealthy

Health Check Parameters

Parameter Description Typical Value Tradeoff
Interval Time between health checks 5-30 seconds Lower = faster detection but more load
Timeout Max time to wait for response 2-10 seconds Lower = faster detection but false positives
Unhealthy Threshold Consecutive failures before marking unhealthy 2-5 checks Lower = faster detection but less tolerance
Healthy Threshold Consecutive successes before marking healthy 2-10 checks Higher = avoids flapping but slower recovery

Connection Draining

Problem: When server marked unhealthy or removed, in-flight requests should complete gracefully.

Solution: Drain period (30-300s) where no new requests route to server, but existing connections allowed to finish. After drain timeout, forcibly close remaining connections.

sequenceDiagram participant LB as Load Balancer participant S as Server participant C1 as Client 1 participant C2 as Client 2 Note over LB,S: Server healthy, receiving traffic C1->>LB: Request 1 LB->>S: Forward S->>LB: Response LB->>C1: Response Note over LB,S: Health check fails LB->>S: Health check S--xLB: Timeout Note over LB,S: Server marked "draining" (no new traffic) C2->>LB: Request 2 LB->>C2: Route to different server C1->>LB: Request 3 (existing conn) LB->>S: Forward (allow existing) S->>LB: Response LB->>C1: Response Note over LB,S: After drain timeout (300s), close all connections LB->>S: Close connection

Health Check Endpoint Design

// Good: Lightweight, checks critical dependencies
GET /health
Response 200 OK:
{
  "status": "healthy",
  "database": "connected",
  "cache": "connected",
  "uptime": 3600
}

Response 503 Service Unavailable:
{
  "status": "unhealthy",
  "database": "timeout",
  "cache": "connected"
}

// Bad: Too expensive, causes cascading failures
GET /health β†’ triggers full DB query + cache warmup
Interview Tip: Health checks prevent cascading failures. Mention active (periodic probes) vs passive (monitor real traffic). Key parameters: interval, timeout, unhealthy threshold. Connection draining avoids abrupt termination. Health check endpoint should be lightweight but validate critical dependencies.

5. Session Affinity (Sticky Sessions)

Problem: Stateful applications store session data in memory. If user's requests load balance to different servers, session lost.

Solution: Ensure user's requests always route to the same server (sticky sessions), OR externalize session storage (preferred).

Method How It Works Pros Cons
Cookie-Based LB sets cookie (e.g., AWSALB=server-id), routes based on cookie Works across IPs, survives NAT, standard for HTTP Requires cookie support, LB must parse HTTP
IP Hash Hash(client IP) β†’ deterministic server Works at L4, no cookies needed Breaks if client IP changes (mobile), uneven with NAT
Header-Based Hash(User-Agent) or Hash(X-Session-ID) β†’ server Flexible, custom logic Requires L7 LB, depends on client sending header
Application-Controlled App generates token, encodes server ID, client sends in request Most control, works with any LB algorithm Requires app changes

Sticky Sessions vs Externalized Sessions

Aspect Sticky Sessions Externalized Sessions (Redis/DB)
Architecture Session stored in server memory Session stored in shared Redis/DB
Scalability Limited (server failure loses sessions) High (stateless servers, horizontal scaling)
High Availability Low (server death = session loss) High (sessions survive server failures)
Load Distribution Uneven (users stuck to servers) Even (any server handles any request)
Deployment Complex (drain connections during deploy) Simple (kill servers anytime)
Latency Lower (in-memory access) Higher (network call to Redis, ~1-5ms)
Cost Lower (no external store) Higher (Redis cluster costs)
Use Case Legacy apps, WebSockets, small scale Modern apps, cloud-native, high scale
graph TB subgraph "Sticky Sessions (Problematic)" C1[Client A] -->|Cookie: server1| LB1[Load Balancer] C2[Client B] -->|Cookie: server2| LB1 LB1 -->|Always routes| S1[Server 1
Session A in memory] LB1 -->|Always routes| S2[Server 2
Session B in memory] S1 -.->|If crashes| X[Sessions Lost] end subgraph "Externalized Sessions (Preferred)" C3[Client A] -->|Request| LB2[Load Balancer] C4[Client B] -->|Request| LB2 LB2 -->|Any request| S3[Server 1] LB2 -->|Any request| S4[Server 2] S3 <-->|Read/Write session| R[Redis Cluster] S4 <-->|Read/Write session| R end
Interview Tip: Sticky sessions are an anti-pattern for modern systems. They break horizontal scaling, cause uneven load, and lose sessions on server failure. Correct answer: externalize sessions to Redis/Memcached. Only use sticky sessions for legacy apps or WebSockets where connection state must live on server.

6. SSL Termination

Key decision: Where to decrypt HTTPS traffic? Three models: terminate at LB, pass through to backend, or re-encrypt (bridge mode).

Model How It Works Pros Cons Use Case
SSL Termination LB decrypts HTTPS, forwards plain HTTP to backends Simple, LB can inspect/route by content, reduced backend CPU Plain HTTP in internal network (security risk), single cert location Trusted internal network, cost-sensitive, need L7 routing
SSL Passthrough LB forwards encrypted traffic (L4), backend decrypts End-to-end encryption, backend controls certs No L7 routing, higher backend CPU, can't inspect traffic Zero-trust network, compliance (PCI-DSS), per-tenant certs
SSL Bridging (Re-encrypt) LB decrypts, inspects, then re-encrypts to backend L7 routing + end-to-end encryption High CPU cost (2x crypto), complex config Zero-trust + need L7 features, strict security
graph LR subgraph "SSL Termination" C1[Client] -->|HTTPS| LB1[Load Balancer] LB1 -->|Decrypt| LB1 LB1 -->|HTTP| S1[Server] style LB1 fill:#f96 end subgraph "SSL Passthrough" C2[Client] -->|HTTPS| LB2[Load Balancer L4] LB2 -->|HTTPS
no decrypt| S2[Server] S2 -->|Decrypt| S2 style LB2 fill:#9f9 end subgraph "SSL Bridging" C3[Client] -->|HTTPS| LB3[Load Balancer] LB3 -->|Decrypt| LB3 LB3 -->|Inspect| LB3 LB3 -->|Encrypt| LB3 LB3 -->|HTTPS| S3[Server] S3 -->|Decrypt| S3 style LB3 fill:#99f end

SSL Termination Flow

sequenceDiagram participant C as Client participant LB as Load Balancer participant S as Backend Server Note over C,LB: TLS Handshake C->>LB: ClientHello LB->>C: ServerHello + Certificate C->>LB: Key Exchange Note over C,LB: Encrypted tunnel established C->>LB: HTTPS Request (encrypted) LB->>LB: Decrypt with private key LB->>LB: Inspect headers, route by /api/users LB->>S: HTTP Request (plaintext) S->>LB: HTTP Response LB->>LB: Encrypt with session key LB->>C: HTTPS Response (encrypted)

Certificate Management

Aspect Centralized (LB) Distributed (Backends)
Certificate Storage LB stores certs (AWS ACM, secrets manager) Each server stores own cert
Renewal Renew once at LB Renew on all servers
SNI Support LB can host multiple certs (SNI) Each server independently handles SNI
Complexity Low (single point) High (N servers to manage)
Interview Tip: SSL termination at LB is most common (simpler, enables L7 routing, reduces backend CPU). Passthrough is for security-critical systems (PCI-DSS, zero-trust). Re-encryption is rare (expensive) but needed when you need both L7 routing AND end-to-end encryption. Mention SNI (Server Name Indication) for hosting multiple domains on one LB.

7. Global Server Load Balancing (GSLB)

Problem: Users worldwide need to route to nearest datacenter for low latency and high availability across regions.

Solution: DNS-based routing (GeoDNS), Anycast IP, or latency-based routing to direct users to optimal datacenter.

Method How It Works Pros Cons
GeoDNS DNS server returns IP based on client's geographic location Simple, works at DNS layer, no app changes Coarse granularity (country-level), DNS caching delays failover (TTL)
Anycast Same IP announced from multiple datacenters, BGP routes to nearest Instant failover, true "nearest" routing via BGP, no DNS caching issues Requires BGP peering, complex setup, stateful protocols break on failover
Latency-Based Routing Route 53 measures latency, returns lowest-latency endpoint Better than geo (accounts for network conditions), automatic AWS-specific, DNS caching still an issue
Health-Based Failover DNS returns primary DC, failover to secondary if primary unhealthy Automatic DR, simple active-passive setup Slow (DNS TTL delay), coarse failover

GSLB Architecture

graph TB C1[Client US] -->|DNS Query| DNS[GeoDNS / Route 53] C2[Client EU] -->|DNS Query| DNS C3[Client Asia] -->|DNS Query| DNS DNS -->|Returns US IP| LB1[LB US-East] DNS -->|Returns EU IP| LB2[LB EU-West] DNS -->|Returns Asia IP| LB3[LB AP-Southeast] LB1 --> S1[Servers US] LB2 --> S2[Servers EU] LB3 --> S3[Servers Asia] S1 <-->|Replicate data| DB[(Global DB
Cross-region replication)] S2 <-->|Replicate data| DB S3 <-->|Replicate data| DB

Anycast vs GeoDNS

graph TB subgraph "GeoDNS" C1[Client EU] -->|1. DNS Query| GEO[GeoDNS] GEO -->|2. Returns EU IP
203.0.113.10| C1 C1 -->|3. HTTP to 203.0.113.10| DC1[EU Datacenter] end subgraph "Anycast" C2[Client EU] -->|HTTP to 1.2.3.4| ANY[Internet
BGP Routing] ANY -->|Routes to nearest| DC2[EU Datacenter
1.2.3.4] ANY -.->|Also announces| DC3[US Datacenter
1.2.3.4] ANY -.->|Also announces| DC4[Asia Datacenter
1.2.3.4] end

Failover Strategies

Strategy Description Failover Time Use Case
Active-Passive Primary DC serves traffic, secondary on standby 1-5 minutes (DNS TTL) Cost-sensitive, DR only
Active-Active All DCs serve traffic, user routed to nearest Instant (traffic re-routes to healthy DCs) High availability, global users
Active-Active-Passive Two DCs active (US, EU), one passive (Asia) Instant for active DCs, 1-5min for passive Regional presence + DR

Route 53 Routing Policies

// Latency-based routing
example.com β†’ Route 53
  - US-East: 54.123.45.67 (latency: 10ms from client)
  - EU-West: 18.234.56.78 (latency: 120ms from client)
  β†’ Returns 54.123.45.67

// Geolocation routing
Client from Germany β†’ Returns EU IP
Client from USA β†’ Returns US IP
Client from Brazil β†’ Returns default (US IP)

// Weighted routing (canary / blue-green)
example.com:
  - 90% β†’ Production (v1.0)
  - 10% β†’ Canary (v2.0)

// Failover routing
Primary: US-East (healthy) β†’ Return US IP
Primary: US-East (unhealthy) β†’ Return EU IP
Interview Tip: GSLB is DNS-based routing to nearest datacenter. GeoDNS is simplest (but DNS caching delays failover). Anycast is best for true instant failover but requires BGP. Route 53 offers latency-based (better than geo), weighted (canary), and failover policies. Mention DNS TTL tradeoff: low TTL = faster failover but more DNS queries.

8. Software vs Hardware Load Balancers

Shift: Industry moving from expensive hardware LBs (F5, Citrix) to software LBs (HAProxy, Nginx, Envoy) and cloud-managed (AWS ALB/NLB).

Load Balancer Type Layer Performance Cost Use Case
HAProxy Software L4 + L7 1M+ conn, 100k RPS Free On-prem, high performance, full control
Nginx Software L7 50k RPS Free (OSS) / Paid (Plus) Web servers, reverse proxy, API gateway
Envoy Software L7 100k RPS Free Service mesh, microservices, modern observability
AWS ALB Managed L7 Auto-scales $0.008/hr + $0.008/LCU AWS HTTP/gRPC, path-based routing, managed certs
AWS NLB Managed L4 Millions RPS, <1ms $0.0225/hr + $0.006/NLCU Ultra-low latency, static IP, non-HTTP protocols
GCP Load Balancer Managed L4 + L7 Auto-scales globally Pay per GB GCP, global anycast, CDN integration
F5 BIG-IP Hardware L4 + L7 Very high $50k-$500k Legacy enterprise, advanced features, vendor support
Citrix ADC Hardware L4 + L7 Very high $30k-$300k Enterprise, app acceleration, SSL offload
IPVS (Linux) Software L4 Very high Free Kernel-level LB, Kubernetes kube-proxy (ipvs mode)

Feature Comparison

Feature HAProxy Nginx Envoy AWS ALB AWS NLB
HTTP/2 Yes Yes Yes Yes No (L4)
gRPC Yes Yes Yes (native) Yes Yes (passthrough)
WebSocket Yes Yes Yes Yes Yes
SSL Termination Yes Yes Yes Yes (ACM) Yes (TLS)
Path-Based Routing Yes Yes Yes Yes No (L4)
Host-Based Routing Yes Yes Yes Yes No (L4)
Rate Limiting Yes Yes Yes No (use WAF) No
Dynamic Config Reload Reload Hot reload (xDS) Automatic Automatic
Observability Logs, stats page Logs, stub_status Prometheus, tracing CloudWatch CloudWatch
Service Mesh No No Yes (Istio data plane) No No

Software LB Architecture

graph TB subgraph "Traditional (Hardware)" C1[Clients] --> HW[F5 Hardware LB
$200k, single point] HW --> S1[Servers] end subgraph "Modern (Software)" C2[Clients] --> LB1[HAProxy Instance 1] C2 --> LB2[HAProxy Instance 2] C2 --> LB3[HAProxy Instance 3] LB1 --> S2[Servers] LB2 --> S2 LB3 --> S2 DNS[DNS Round Robin] -.->|Distributes| LB1 DNS -.->|Distributes| LB2 DNS -.->|Distributes| LB3 end
Interview Tip: Software LBs (HAProxy, Nginx, Envoy) have replaced hardware in most modern systems. HAProxy is gold standard for performance. Envoy is standard for service mesh (Istio, Consul). AWS ALB for L7 (path routing), NLB for L4 (ultra-low latency, static IP). Mention Envoy's xDS API for dynamic config without restarts.

9. High Availability of Load Balancers

Problem: Load balancer is a single point of failure. If LB dies, entire system is down.

Solution: Active-passive pairs with VRRP, active-active with DNS round robin, or BGP anycast for multi-LB resilience.

Method How It Works Pros Cons Use Case
Active-Passive (VRRP) Two LBs share virtual IP (VIP), active sends heartbeats, passive takes over on failure Simple, fast failover (1-3s), standard protocol (VRRP/keepalived) Passive wastes capacity, single region On-prem, single DC, cost-sensitive
Active-Active (DNS RR) DNS returns multiple IPs, client connects to any Full capacity utilization, simple DNS caching delays failure detection, uneven load Stateless HTTP, tolerant of slow failover
BGP Anycast Multiple LBs announce same IP via BGP, routers send to nearest Instant failover, true active-active, multi-region Requires BGP peering, complex, stateful conns break Global CDNs, DDoS mitigation, DNS servers
Elastic/Managed LB Cloud provider handles HA (AWS ALB/NLB multi-AZ) Fully managed, auto-scales, multi-AZ by default Vendor lock-in, less control Cloud-native apps, rapid deployment

VRRP (Active-Passive) Architecture

graph TB C[Clients] -->|Connect to VIP
192.168.1.100| VIP[Virtual IP] VIP -.->|Owned by| LB1[LB1 Active
Priority 200] VIP -.->|Standby| LB2[LB2 Passive
Priority 100] LB1 -->|Heartbeat every 1s| LB2 LB1 -->|Routes traffic| S[Backend Servers] LB2 -.->|On LB1 failure| VIP2[Takes over VIP
ARP announcement] VIP2 -.->|Routes traffic| S

VRRP Failover Process

sequenceDiagram participant C as Client participant VIP as Virtual IP participant LB1 as LB1 (Active) participant LB2 as LB2 (Passive) participant S as Server Note over LB1,LB2: Normal operation LB1->>LB2: VRRP Advertisement (every 1s) C->>VIP: Request VIP->>LB1: Forward (LB1 owns VIP) LB1->>S: Proxy request S->>LB1: Response LB1->>C: Response Note over LB1,LB2: LB1 failure detected LB2->>LB2: No advertisement for 3s LB2->>LB2: Transition to ACTIVE LB2->>VIP: Gratuitous ARP (claim VIP) Note over LB1,LB2: LB2 now active C->>VIP: Request VIP->>LB2: Forward (LB2 owns VIP) LB2->>S: Proxy request S->>LB2: Response LB2->>C: Response

Multi-AZ AWS ALB Architecture

graph TB C[Clients] -->|DNS: example.com| DNS[Route 53] DNS -->|Returns ALB DNS| ALB[ALB
multi-AZ by default] ALB -->|Distributes| AZ1[Availability Zone 1
us-east-1a] ALB -->|Distributes| AZ2[Availability Zone 2
us-east-1b] ALB -->|Distributes| AZ3[Availability Zone 3
us-east-1c] AZ1 --> S1[Servers in AZ1] AZ2 --> S2[Servers in AZ2] AZ3 --> S3[Servers in AZ3] Note[AWS manages LB nodes
in each AZ automatically]

LB HA Comparison

Aspect VRRP (Active-Passive) DNS RR (Active-Active) BGP Anycast AWS ALB
Failover Time 1-3 seconds 30-300 seconds (DNS TTL) Instant (BGP convergence <1s) Instant (managed)
Capacity Usage 50% (passive idle) 100% (all active) 100% (all active) 100% (auto-scale)
Complexity Medium (keepalived config) Low (DNS only) High (BGP peering) Low (managed)
Multi-Region No (single VIP) Yes (DNS per region) Yes (anycast globally) Yes (cross-region LB)
Stateful Connections Breaks on failover Unaffected (per-connection) Breaks on failover Breaks on failover
Interview Tip: LB itself is a SPOF without HA. VRRP/keepalived is standard for on-prem (1-3s failover). Cloud-managed LBs (ALB/NLB) are multi-AZ by default (easiest). Anycast is for global scale (CDNs, DNS). Mention floating IP (VIP) and gratuitous ARP for L2 failover.

10. Advanced Load Balancing Patterns

Rate Limiting

Protect backend from overload by limiting requests per client. Implemented via token bucket or leaky bucket algorithms.

Algorithm How It Works Use Case
Token Bucket Bucket holds N tokens, request consumes token, tokens refill at rate R/sec Burst traffic allowed (up to bucket size)
Leaky Bucket Requests enter queue, processed at fixed rate R/sec, overflow dropped Smooth traffic, no bursts
Fixed Window Allow N requests per time window (e.g., 1000/min) Simple but allows 2N requests at window boundary
Sliding Window Count requests in rolling time window (last 60 seconds) More accurate than fixed window
// Nginx rate limiting
http {
    limit_req_zone $binary_remote_addr zone=api:10m rate=100r/m;

    server {
        location /api/ {
            limit_req zone=api burst=20 nodelay;
            # Allow 100 req/min per IP, burst up to 20
        }
    }
}

Connection Draining

Gracefully remove servers from pool: stop sending new connections, allow existing to complete, timeout after drain period (e.g., 300s).

stateDiagram-v2 [*] --> Healthy: Server starts Healthy --> Draining: Deploy / Health check fail Draining --> Removed: Drain timeout (300s) OR all connections closed Removed --> [*]: Server shutdown note right of Draining: No new connections, Existing connections allowed, Max 300s wait

Canary Deployments

Route small percentage (1-10%) of traffic to new version, monitor errors, gradually increase if healthy.

Stage Canary % Production % Action
Initial 1% 99% Deploy v2 to 1%, monitor for 30min
Expand 10% 90% If healthy, increase to 10%
Half 50% 50% If healthy, 50/50 split
Full 100% 0% If healthy, complete rollout
Rollback 0% 100% If errors, instant rollback
graph LR C[Clients] --> LB[Load Balancer] LB -->|90% traffic| P[Production v1.0
10 servers] LB -->|10% traffic| CA[Canary v2.0
2 servers] M[Metrics] -.->|Monitor| CA M -.->|Error rate OK?| D{Decision} D -->|Yes| INC[Increase canary %] D -->|No| RB[Rollback to 0%]

Blue-Green Deployments

Two identical environments (blue=production, green=new version). Deploy to green, test, then switch LB to route 100% to green.

graph TB subgraph "Before Switch" LB1[Load Balancer] -->|100% traffic| B1[Blue Environment
v1.0] G1[Green Environment
v2.0] -.->|Deployed, testing| G1 end subgraph "After Switch" LB2[Load Balancer] -->|100% traffic| G2[Green Environment
v2.0] B2[Blue Environment
v1.0] -.->|Standby for rollback| B2 end
Pattern Rollout Rollback Cost Use Case
Rolling Gradual (2 servers at a time) Re-deploy old version Low Default for most apps
Canary Gradual (1% β†’ 10% β†’ 50% β†’ 100%) Instant (change %) Low Risk-averse, need metrics
Blue-Green Instant (flip LB) Instant (flip back) High (2x infra) Zero-downtime, instant rollback critical

A/B Testing via LB

Route users to different versions based on criteria (header, cookie, user ID) to compare behavior/performance.

// Envoy A/B routing
routes:
  - match:
      prefix: "/api"
      headers:
        - name: "X-Experiment"
          exact_match: "variant-b"
    route:
      cluster: service_variant_b
  - match:
      prefix: "/api"
    route:
      weighted_clusters:
        clusters:
          - name: service_variant_a
            weight: 50
          - name: service_variant_b
            weight: 50

Circuit Breaking at LB

LB detects backend failure patterns (high error rate, timeouts) and temporarily stops routing to unhealthy backend, preventing cascading failures.

stateDiagram-v2 [*] --> Closed: Normal operation Closed --> Open: Error threshold exceeded
(e.g., 50% errors in 10s) Open --> HalfOpen: After timeout (30s) HalfOpen --> Closed: Test requests succeed HalfOpen --> Open: Test requests fail note right of Open: Stop routing to backend, Fail fast, Prevents cascading failures

Retry and Timeout Policies

Policy Configuration Purpose
Request Timeout Max 5s per request Prevent hanging requests
Retry Budget Max 2 retries, only on 5xx/timeout Improve reliability without overload
Retry Backoff Exponential: 100ms, 200ms, 400ms Avoid thundering herd
Idempotency Only retry GET, PUT, DELETE (not POST) Prevent duplicate operations
Interview Tip: Advanced patterns show depth. Rate limiting prevents abuse (token bucket = allow bursts). Canary = gradual rollout with metrics, blue-green = instant switch with rollback. Connection draining = graceful shutdown. Circuit breaker = prevent cascading failures. Retry with backoff and budget.

Real-World Configurations & Benchmarks

Performance Benchmarks

Load Balancer Hardware Connections HTTP/1.1 RPS L4 RPS Latency
HAProxy m5.2xlarge (8 vCPU) 1.2M concurrent 400K/sec 1M/sec <1ms
Nginx m5.2xlarge (8 vCPU) 500K concurrent 300K/sec HTTP N/A (L7 only) 1-3ms
Nginx (HTTPS) m5.2xlarge (8 vCPU) 200K concurrent 80K/sec N/A 3-5ms (TLS overhead)
AWS NLB Managed (auto-scale) Millions 1M+ new conn/sec 1M+/sec <100ΞΌs added
AWS ALB Managed (auto-scale) 100K per target group Auto-scales N/A (L7) ~3ms added

AWS Limits & Characteristics

Load Balancer Key Limits Details
AWS NLB 1M+ new connections/sec, no IP warmup needed Sub-100ΞΌs added latency. Static IPs. Cross-zone load balancing (charges apply).
AWS ALB 100K concurrent connections per target group, 1000 rules limit ~3ms added latency. Path-based/host-based routing. Auto-scaling (no warmup needed since 2019).

Failure Timeline Example

Scenario: Backend server crashes behind a load balancer.

Time Event Impact
T=0s Server dies (crash, OOM, network partition) New requests fail, in-flight requests dropped
T=10s Health check fails (interval 5s Γ— threshold 2) LB marks server unhealthy, removes from pool
T=10s New connections routed to healthy servers New traffic unaffected after detection
T=30s In-flight requests timeout (request timeout 30s) Client receives 504 Gateway Timeout
Total Impact 10s detection lag + 30s for existing connections ~30s total impact for worst-case in-flight requests
Interview Tip: Real-world numbers matter. HAProxy on 8 vCPU = 400K HTTP req/sec is a concrete anchor. AWS NLB has <100ΞΌs added latency (L4 passthrough), while ALB adds ~3ms (L7 inspection). Failure detection time = health check interval Γ— unhealthy threshold (e.g., 5s Γ— 2 = 10s). Connection draining adds 30-300s for graceful shutdown.

Summary