System Design · Core
Load Balancing
Spread traffic across healthy backends: L4 vs L7, algorithms, health checks, sticky sessions, and where TLS terminates.
1. What a load balancer does
A load balancer (LB) is a reverse proxy that accepts client connections and forwards them to a pool of backend instances. Goals: even utilization, hide node failures, and (at L7) route by path, host, or header.
| Benefit | Why it matters |
|---|---|
| Horizontal scale | Add/remove app instances without client changes |
| High availability | Skip unhealthy nodes; survive single-instance failure |
| SSL offload | Terminate TLS once; simplify cert rotation |
| Smart routing | L7 path/host rules, canaries, blue-green |
| Protection | Central place for rate limits, WAF, connection limits |
2. Layer 4 vs Layer 7
| L4 (transport) | L7 (application) | |
|---|---|---|
| Sees | IP + port (TCP/UDP) | HTTP method, path, headers, cookies |
| Speed | Very fast, cheap | More CPU; can inspect/transform |
| Routing | Same pool for all bytes | /api → service A, /media → other pool |
| Examples | NLB, IPVS, LVS | NGINX, Envoy, ALB, HAProxy HTTP mode |
Interview default: L7 at the edge for HTTP APIs; L4 when you need raw TCP (databases, some streaming, gaming sockets).
3. Algorithms
Round robin (RR)
Send request N to backend N % pool_size. Fair when backends
are equal and requests cost similar CPU.
Weighted round robin
Larger machines get higher weight. Useful during canaries (send 5% to the new build).
Least connections
Prefer the backend with fewest open connections. Better for long-lived or uneven work (uploads, WebSockets, slow APIs).
IP hash / consistent hash
Hash client IP (or a key) onto a backend. Improves cache locality and can approximate stickiness without cookies. Prefer consistent hashing when the pool membership changes often.
Least response time
Prefer the backend with the lowest recent latency (sometimes combined with fewest connections). Good when backends are heterogeneous or some are temporarily slow. Needs the LB to track response-time samples; can oscillate if metrics are noisy — use a short moving average.
Random
Pick a backend uniformly at random (or weighted random). Extremely simple, no shared counter state, and statistically fair at high QPS. Worse than least-conn for long-lived uneven work; fine for short, similar-cost HTTP requests.
| Algorithm | Best when | Watch out |
|---|---|---|
| Round robin | Equal backends, similar request cost | Slow node still gets equal share |
| Weighted RR | Mixed instance sizes / canaries | Weights need ops discipline |
| Least connections | Long-lived or uneven work | Needs accurate conn tracking |
| Least response time | Heterogeneous or temporarily slow nodes | Metric noise / oscillation |
| IP / consistent hash | Cache locality, soft stickiness | Uneven clients → hot backends |
| Random | Simple short HTTP at high QPS | Ignores load and latency |
4. Health checks
- Active: LB probes backends on an interval.
- Passive: count 5xx / connection errors; eject after a threshold.
- Deep vs shallow: shallow = process up; deep = can reach DB/cache (risk: cascading fail if a dependency blips).
| Type | What it checks | Typical use |
|---|---|---|
| TCP | Accept connection on port | Fast liveness; no app semantics |
| HTTP | GET /healthz returns 2xx | App process ready to serve |
| Custom / script | App-defined (gRPC health, deep deps) | Readiness with care — avoid shared-dep flaps |
| Knob | Meaning | Interview ballpark |
|---|---|---|
| Interval | How often to probe | 5–30s |
| Timeout | Max wait for a probe response | 2–5s |
| Unhealthy threshold | Fails before remove from pool | 2–3 consecutive fails |
| Healthy threshold | Passes before re-add | 2–5 consecutive passes |
Prefer shallow liveness plus a separate readiness signal. On deploy, mark the instance not-ready, drain connections, then stop.
5. Sticky sessions (session affinity)
Route the same client to the same backend. Use only when you must (legacy in-memory sessions, pinning a WebSocket to a node). Prefer externalizing state so any node works. Stickiness hurts failover and creates hot nodes when one user is heavy.
| Method | How | Trade-off |
|---|---|---|
| Cookie | LB sets cookie naming the backend | Works through NAT; cookie must be trusted/signed |
| IP hash | Hash client IP → backend | Breaks behind shared NAT / mobile carrier IPs |
| URL param | Session id in query/path hashed | Leaks in logs/referrers; awkward for APIs |
6. SSL / TLS termination
- Terminate at LB: simpler cert management; LB can inspect HTTP.
- Pass-through: end-to-end encryption; LB stays L4.
- Re-encrypt: terminate then mTLS to backends for zero-trust.
Offload CPU-heavy crypto to the LB fleet; rotate certs with ACME or a cloud certificate manager.
7. Placement patterns
- Edge LB / API gateway: public entry, auth, rate limit, routing.
- Internal LB: service-to-service inside the VPC.
- DNS LB: multiple A records; coarse, client-cached, no instant health.
- Global LB / anycast: steer users to the nearest region.
8. HA for load balancers
| Active-Passive | Active-Active | |
|---|---|---|
| How | Primary serves; standby takes VIP on fail | Multiple LBs share traffic (ECMP / anycast / DNS) |
| Capacity | Standby mostly idle | All nodes useful under load |
| Failover | Seconds; VIP/ARP move | Often smoother; need shared state care |
| Use when | Simple on-prem pairs | Cloud managed LBs, high QPS edges |
Managed cloud LBs are usually active-active behind the scenes. If you run your own (HAProxy/NGINX), plan VIP failover (Keepalived/VRRP) or put them behind a cloud NLB.
9. LB technologies (interview map)
| Tech | Layer | Notes |
|---|---|---|
| NGINX | L7 (also L4 stream) | Reverse proxy, TLS, path routing; very common |
| HAProxy | L4/L7 | High performance; rich health/stick tables |
| AWS ALB | L7 | HTTP/HTTPS, path/host rules, target groups |
| AWS NLB | L4 | Ultra-low latency TCP/UDP; static IPs |
| Cloudflare | Edge L7 + DNS | Global anycast, WAF, CDN combo |
10. Global load balancing (GSLB)
GSLB steers users to a region or PoP before the regional LB picks an instance. Mechanisms: geo-DNS, latency-based DNS, anycast IP, or a global HTTP front door.
- Pair with multi-region data strategy (active-active vs primary-secondary).
- Say “global entry + regional LB + local pool” in multi-region designs.
11. Failure modes to mention
- LB itself is a SPOF → run active-active pairs or a managed cloud LB.
- Thundering herd when a backend returns → use slow start.
- Health check that depends on a shared DB → all nodes go unhealthy together.
- Connection draining too short → in-flight requests reset.
12. Interview talking points
Draw the LB in front of a pool, name L4 vs L7, pick an algorithm for the workload (least-conn for WebSockets), describe health + drain, and say where TLS ends. If asked about multi-region, add DNS or global LB on top.
Quick revision
- L4 = TCP/UDP; L7 = HTTP-aware routing and headers.
- Algorithms: RR, weighted, least-conn, least-RT, IP hash, random.
- Health: TCP/HTTP/custom; set interval, timeout, healthy/unhealthy thresholds.
- Sticky via cookie / IP / URL param — last resort; externalize state.
- LB HA: active-passive VIP vs active-active; managed LBs preferred.
- GSLB/geo routing for multi-region entry; then regional LB.
- TLS often terminates at LB; drain on deploy; slow-start recoveries.