Load Balancers

Intermediate
Infrastructure

A load balancer distributes incoming traffic across multiple backend servers to prevent any single server from becoming a bottleneck, while providing health checking, SSL termination, and high availability.

Overview

Load balancers are a foundational component of any horizontally scaled system. They operate at either Layer 4 (TCP/UDP — routing based on IP and port) or Layer 7 (HTTP — routing based on URL, headers, cookies). Layer 4 load balancers are faster but less intelligent. Layer 7 load balancers can make smarter routing decisions — sending /api requests to one server pool and /static to another. Load balancing algorithms — round-robin, least connections, IP hash, weighted — determine how traffic is distributed. Health checks ensure traffic is never sent to unhealthy instances. In cloud environments, AWS ALB (Layer 7) and NLB (Layer 4) are the primary choices.

Layer 4 vs Layer 7 Load Balancers

L4 load balancers operate at the transport layer — they forward TCP/UDP packets based on IP and port without inspecting the payload. They are extremely fast (can handle millions of connections) but cannot make content-aware decisions. L7 load balancers terminate the HTTP connection, inspect the request, make a routing decision, then open a new connection to the backend.

L4 vs L7 load balancer comparison
// Layer 4 (TCP/UDP) — AWS Network Load Balancer (NLB)
// Routes based on: destination IP + port + protocol
// Does NOT read HTTP headers, paths, or cookies
// Use cases: non-HTTP protocols (gRPC, WebSocket raw, gaming, IoT),
//            ultra-low latency, millions of concurrent connections
// Connection: client ↔ NLB ↔ backend (TCP passthrough)

// Layer 7 (HTTP/HTTPS) — AWS Application Load Balancer (ALB)
// Reads: URL path, Host header, HTTP method, cookies, query params
// Use cases: microservices routing, A/B testing, auth offload, WebSocket
// Routing rules example:

// Nginx L7 load balancer config:
upstream api_servers {
  least_conn;                     // least-connections algorithm
  server 10.0.1.1:8080 weight=3; // gets 3x more traffic
  server 10.0.1.2:8080 weight=1;
  server 10.0.1.3:8080 backup;   // only used if others are down
}

server {
  listen 443 ssl;
  location /api/     { proxy_pass http://api_servers; }
  location /static/  { proxy_pass http://cdn_servers; }  // content-aware routing
}

Load Balancing Algorithms

The algorithm determines which backend receives the next request. Round-robin is the simplest; least-connections is better when requests have variable processing time; IP hash ensures a client always reaches the same backend (useful for session affinity without sticky cookies); weighted round-robin lets you gradually shift traffic (blue/green deploy).

Load balancing algorithm comparison
// Round Robin — requests distributed sequentially
// Req 1 → Server A, Req 2 → Server B, Req 3 → Server C, Req 4 → Server A...
// Good for: homogeneous requests, stateless apps

// Least Connections — new request goes to server with fewest active connections
// Good for: long-lived connections (WebSocket, file uploads), variable request durations
upstream backend { least_conn; server 10.0.1.1:8080; server 10.0.1.2:8080; }

// IP Hash — hash(client_IP) % n_servers → same server every time
// Good for: session affinity without shared session store
upstream backend { ip_hash; server 10.0.1.1:8080; server 10.0.1.2:8080; }

// Weighted Round Robin — blue/green or canary deployments
upstream backend {
  server 10.0.1.1:8080 weight=95;  // v1 — 95% of traffic
  server 10.0.1.2:8080 weight=5;   // v2 — 5% canary
}

// Random with Two Choices (Power of Two) — pick 2 random servers,
// route to the one with fewer connections. Scales better than least-conn
// (avoids "thundering herd" on the globally least-loaded server)

Health Checks & Connection Draining

Health checks periodically probe backends and remove unhealthy instances from the pool. Connection draining (deregistration delay) allows in-flight requests to complete before a backend is fully removed — critical for zero-downtime deployments.

Health checks and connection draining
// Nginx active health check (nginx-plus / openresty):
upstream api_servers {
  server 10.0.1.1:8080;
  server 10.0.1.2:8080;
  check interval=3000 rise=2 fall=3 timeout=1000 type=http;
  check_http_send "GET /health HTTP/1.0\r\n\r\n";
  check_http_expect_alive http_2xx http_3xx;
}
// rise=2: mark healthy after 2 consecutive successes
// fall=3: mark unhealthy after 3 consecutive failures

// AWS ALB health check (Terraform):
resource "aws_lb_target_group" "api" {
  health_check {
    path                = "/actuator/health"
    interval            = 30           // check every 30s
    healthy_threshold   = 2
    unhealthy_threshold = 3
    timeout             = 5
    matcher             = "200"
  }
  deregistration_delay = 30           // 30s connection draining
}

// Spring Boot health endpoint:
// GET /actuator/health → { "status": "UP" }

SSL Termination & Sticky Sessions

SSL termination at the load balancer means the LB decrypts HTTPS traffic and communicates with backends over plain HTTP — reducing CPU load on backends. Sticky sessions (session affinity) bind a user's requests to the same backend via a cookie, useful for stateful apps but it undermines even load distribution.

SSL termination and sticky sessions
// SSL Termination at load balancer:
// Client ──HTTPS──▶ [Load Balancer: decrypt TLS] ──HTTP──▶ Backend
// Benefits: offloads crypto from backends, centralise certificate management
// Nginx SSL termination:
server {
  listen 443 ssl;
  ssl_certificate     /etc/ssl/aicancode.org.crt;
  ssl_certificate_key /etc/ssl/aicancode.org.key;
  ssl_protocols TLSv1.2 TLSv1.3;
  ssl_ciphers ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384;
  location / { proxy_pass http://api_servers; }
}

// Sticky Sessions (session affinity) — AWS ALB:
resource "aws_lb_target_group" "api" {
  stickiness {
    type            = "lb_cookie"
    cookie_duration = 86400    // 1 day
    enabled         = true
  }
}
// ALB sets AWSALB cookie on first response
// Subsequent requests with same cookie → same backend

// Better alternative: externalise session state
// Store session in Redis → any backend can serve any request (stateless)

Key Points to Remember

  • 1L4 load balancers route by IP/port (fast, protocol-agnostic); L7 route by HTTP content (smarter, enables path-based routing).
  • 2Least-connections is better than round-robin when request processing times vary significantly.
  • 3IP hash provides session affinity without shared state — but better practice is to externalise session to Redis.
  • 4Connection draining (deregistration delay) allows in-flight requests to complete before removing an instance — enables zero-downtime deployments.
  • 5AWS ALB is the default choice for HTTP microservices; NLB for non-HTTP protocols or ultra-low latency TCP.

Interview Questions

Sign in to ask Aria
1

What is the difference between a Layer 4 and Layer 7 load balancer?

MediumAmazon
2

When would you use NLB over ALB in AWS?

MediumThoughtWorks
3

What is connection draining and why is it important for deployments?

MediumFlipkart
4

How do sticky sessions work and what problems do they cause?

MediumRazorpay
5

How does the "power of two random choices" algorithm improve on least-connections?

HardEqual Experts

Ask Aria about Load Balancers

Your personal AI tutor — ask anything about this concept

Revision Status

Personal Notes

Sign in to save personal notes for this topic.

Discussion

Sign in to join the discussion.

Loading discussion…