CMD Guide
HomeSystem DesignLoad Balancing

Introduction to Load Balancing

A load balancer works by terminating the client's connection itself, then — per request or per connection — picking one backend from a pool it continuously health-checks, and forwarding the traffic there; because the pool membership and the pick are the load balancer's decision, a dead server is simply skipped and no single server ever sees more than its share.

That single mechanism is what buys you three things at once: availability (traffic routes around a failed node), scalability (add a node to the pool and it starts absorbing load), and performance (spread the work so no box saturates). The load balancer sits in the request path between the caller and the servers, which is also why it becomes the place you centralize concerns like TLS.

diagram
diagram

Where load balancers sit

You rarely have just one. To get scalability and redundancy at every tier, you balance load at each hop where a many-to-many relationship exists between callers and servers:

Each layer can fail independently, so each layer gets its own pool and its own health checks.

Traced example: round-robin across a burst, with a failure mid-stream

Three identical backends S1, S2, S3. The balancer keeps a rotating index over its healthy list and hands each new request to the next entry. A health check runs every few seconds. Eight requests arrive; between r4 and r5 the checker marks S2 down (two consecutive failed probes), so the healthy list shrinks to [S1, S3] and the rotation continues over the survivors.

RequestHealthy poolRotation indexRouted toNote
r1S1,S2,S30S1
r2S1,S2,S31S2
r3S1,S2,S32S3
r4S1,S2,S30S1
Health check: S2 fails 2 probes → removed from pool
r5S1,S31S3rotation lands on dead S2 → skipped → S3
r6S1,S30S1
r7S1,S31S3
r8S1,S30S1

(This balancer continues its rotation and skips the dead entry — after r4 hit S1, the next slot was S2, now dead, so r5 falls through to S3. An implementation that instead resets its rotation index when the healthy list changes would send r5 to S1 — same totals, different order.)

Result: S1 served 4, S3 served 3, S2 served 1 and then zero — the client never saw an error, because the balancer stopped choosing S2 the moment it failed the probe. This is the whole value proposition in one trace: even distribution while everything is up, automatic routing-around when something dies.

Where naive round-robin goes wrong: it assumes requests are equal cost. If S1 gets stuck on a slow 30-second query while S3 handles 1 ms cache hits, round-robin keeps piling requests onto the overloaded S1 anyway. That is the motivation for least-connections (route to the backend with the fewest in-flight requests) — in the trace above, once S1 is deep in slow work, least-connections would steer new requests to S3 instead of blindly alternating.

The parts that make it work

The mechanism above only holds up because of a few supporting pieces. Each one exists to solve a concrete failure, not as vocabulary:

PieceWhat it doesThe failure it prevents
Health checksPeriodic probes (TCP connect, or an HTTP GET /healthz); N failures eject a node, M successes re-add it.Sending traffic into a black hole — a crashed or overloaded node the balancer hasn't noticed yet.
Session persistence (sticky sessions)Pins a client to one backend, usually via a cookie or client-IP hash.A user losing their in-memory session (cart, login) when the next request lands on a different node.
TLS terminationDecrypts HTTPS at the balancer so backends speak plain HTTP internally.Every backend re-doing expensive crypto and each needing its own certificate/key management.
Connection drainingStops sending new requests to a node being removed, but lets in-flight ones finish.Cutting off live requests (dropped uploads, half-written responses) during a deploy or scale-down.

Pitfalls

When to reach for a load balancer — and when not to

Signals that point here: you run more than one instance of a service, you need zero-downtime deploys, you must survive a single node dying, or one box can no longer hold peak traffic. If any of those is true, put a balancer in front.

When NOT to: a single instance that fits your traffic with headroom does not need one — a balancer adds an extra hop, operational surface, and a new failure domain for zero benefit. Add it when you actually have (or are about to have) more than one backend.

Versus the named alternatives

Takeaways

Drill ladder — survive the follow-ups

L0 · A load balancer picks one healthy backend per request/connection so no single server is a bottleneck or a hard dependency.

L1 · ① Concurrency — "round-robin sends each request to the next server — does that balance load?"
Trap: "yes — every server gets an equal share of requests, so it's balanced."
Bar: Round-robin balances request count, not request cost — a backend stuck on a 30s query keeps receiving new requests at the same rate as an idle one. Least-connections routes by current in-flight count instead, and power-of-two-choices (sample 2 random backends, pick the less-loaded) gets near-optimal balance without a global connection registry. connects-to: algorithms traced

L2 · ② Failure — "a backend crashes mid-traffic — what actually happens to requests in that window?"
Trap: "the health check catches it right away, so impact is basically zero."
Bar: Health checks only fire every few seconds and require N consecutive failed probes before ejecting a node, so requests routed during that detection window hit a dead or hanging backend and time out; a shallow TCP-connect probe makes it worse by passing while the app itself returns 500s. connects-to: health probes

L3 · ⑤ Adversary/Edge — "clients auto-retry failed requests — that's just good defensive engineering, right?"
Trap: "retries make the system more reliable, so more retries is strictly safer."
Bar: Retries without backoff and jitter re-send the same load back onto backends that are already failing or overloaded — a retry storm — turning a partial degradation into a full outage; the fix is capped retries with exponential backoff+jitter plus a circuit breaker that stops calling a backend once it's clearly down. connects-to: retry pattern

L4 · ④ Time/Lifecycle — "you just added a fourth server to the pool — does it start pulling its fair share immediately?"
Trap: "sure, round-robin/least-conn gives it equal treatment from request one."
Bar: A cold node has no warmed cache, no JIT-compiled hot paths, and possibly no primed connection pool to the database, so dumping full rotation share on it immediately spikes its latency and can trip health checks into ejecting it again; slow-start ramps its assigned weight up over tens of seconds so traffic grows only as fast as the node proves it's ready. connects-to: tier sizing & slow-start

L5 · ⑥ Cost/Simplicity + ② Failure — "you've made the backend tier resilient — what protects you from the load balancer itself dying?"
Trap: "put a bigger, more reliable box in front — that's the fix."
Bar: A single load balancer is now the SPOF for the entire tier no matter how reliable the box is; run at least two — active-passive sharing a floating/virtual IP via VRRP/keepalived with health-checked failover, or active-active behind anycast/ECMP — so losing one balancer doesn't take down everything behind it. connects-to: failover mechanics

The floor keeps dropping: "your 'least connections' is actually 30 independent LB instances behind ECMP with no shared counter — each only sees its own slice of traffic, so 'least loaded' is a local illusion, not a global fact." And don't reach for L7 as a free fix: L7 sees headers and paths and can retry idempotent requests intelligently, but it terminates TLS and parses every request, costing real CPU per hop — L4 stays blind but cheap. The actual fix for the shared-state problem is either a low-latency shared counter (accepting some staleness) or switching the metric to something local-only, like EWMA response time, that doesn't need global truth to work well.

Self-locate: died at L1 → mid-level; L4+ → staff signal.

Facing any new concept? Hit it with the six: concurrent? failing? at 100×? over time? adversarial? worth the cost? — that's the interviewer's whole playbook.


Re-authored and deepened for this guide. Synthesized from NGINX and HAProxy load-balancing documentation (algorithms, health checks, slow-start, connection draining), the AWS Elastic Load Balancing developer guide (L4/L7 and TLS termination), the Google SRE book (health checking and load-balancing frontends), and Grokking the System Design Interview (layered placement of load balancers). The round-robin trace and failure scenarios are hand-constructed.

🤖 Don't fully get this? Learn it with Claude

Stuck on Introduction to Load Balancing? Open Claude, copy a block below, and it'll teach you this exact concept — visually and interactively.

🎨 Explain it visually

Build the mental picture, not memorization.

I just read a lesson on **Introduction to Load Balancing** (System Design) and want to truly understand it. Explain Introduction to Load Balancing from first principles using ONE vivid real-world analogy and a visual mental model — draw it as ASCII art or a clear step-by-step diagram — with a concrete example using real numbers. Then ask me one question to check I got the mental picture, and wait for my reply. If you're unsure or a claim isn't standard, say so and reason from first principles instead of guessing.
🤔 Walk me through it (interactive)

Socratic — adapts to where you're stuck.

Teach me **Introduction to Load Balancing** interactively. Ask me ONE guiding question at a time, wait for my answer, and adapt to my confusion — build the idea with me step by step instead of explaining it all at once. If you're unsure or a claim isn't standard, say so and reason from first principles instead of guessing.
🧪 Quiz me & fix my gaps

Active recall exposes what you missed.

Quiz me on **Introduction to Load Balancing** with 5 questions, easy to tricky, ONE at a time. Tell me if each answer is right; at the end, explain clearly what I got wrong and why. If you're unsure or a claim isn't standard, say so and reason from first principles instead of guessing.
🧠 Make it stick

Intuition + hook + flashcards for long-term memory.

Help me remember **Introduction to Load Balancing** for the long term: give the one-sentence intuition, a memorable hook/mnemonic, a tiny worked example, and 3 active-recall flashcards (Q -> A). If you're unsure or a claim isn't standard, say so and reason from first principles instead of guessing.

📝 My notes