ulearn/systems

topics / traffic-routing

Load Balancer

Round robin, least connections, weighted and IP-hash routing across a pool of backends. Break one on purpose and watch the routing decision change.

What a load balancer actually does

A load balancer sits between clients and a pool of backend servers. Every incoming request has to be assigned to exactly one backend — that assignment rule is the “algorithm”. Switch it in the simulation and watch the same traffic pattern get distributed completely differently.

Routing algorithms

Round robin

Cycles through backends in fixed order: 1, 2, 3, 1, 2, 3… Simple and fair by request count, but blind to how long each backend takes — a slow backend gets the same share of traffic as a fast one.

Least connections

Sends each new request to whichever backend currently has the fewest active requests. Self-correcting: a backend that's falling behind naturally gets less new traffic until it catches up.

Weighted round robin

Like round robin, but backends with a higher weight get proportionally more requests. Used when backends have different capacity (a bigger instance should take more load). This simulation uses the same “smooth” weighting algorithm nginx uses, so traffic is interleaved rather than sent in bursts.

IP hash

Hashes the client's address to consistently pick the same backend for the same client — useful for sticky sessions. The catch: if the set of healthy backends changes (one goes down), the hash-to-backend mapping shifts for everyone, not just the clients that were using the failed backend. That reshuffling problem is what consistent hashing exists to fix.

URL hash

Same idea as IP hash, but keyed on the requested path instead of the client address — the same URL always lands on the same backend, which is what makes per-backend caching effective. It shares IP hash's reshuffling problem when the backend pool changes, and it doesn't give any one client session affinity the way IP hash does.

Random

Picks a backend uniformly at random for every request, no state kept between picks. Over enough requests it evens out about as well as round robin, but individual bursts can still land unevenly since nothing coordinates one pick with the next.

Failure modes, and what the load balancer should do about each

  • Backend goes down— the LB has to detect it (usually via failed health checks) and stop routing to it. In the simulation this happens automatically after 3 consecutive failed requests, mirroring how a real health check takes a few misses before it declares a backend dead. Toggle “Kill” to simulate a hard crash directly.
  • Backend is slow— the backend still responds, just later. This doesn't trip health checks on its own, which is exactly why it's dangerous: a slow backend keeps receiving traffic (especially under round robin) and its request queue backs up.
  • Backend returns errors— the connection succeeds but the response is a failure (5xx). This counts against the backend's consecutive-failure count the same as a hard failure would.
  • Backend is overloaded — it has hit its own connection limit and starts refusing new connections outright, rather than queuing them. Notice this can also happen organically in the simulation if too many concurrent requests land on one backend — try IP hash during a DDoS and watch a handful of unlucky backends drown while others sit idle.
  • Timeout— the backend never responds at all. A real LB waits until its timeout budget expires, then gives up and — if it's configured to — retries the request on a different backend. That's what the simulation does: one retry, then a final timeout if the retry also fails.

DDoS traffic

A denial-of-service flood looks different from normal traffic in two ways the simulation models directly: a much higher request rate, and requests coming from many distinct (often spoofed) source addresses rather than a handful of regular clients.

The rate alone is often enough to push backends into organic overload regardless of algorithm. But the algorithm still matters: round robin and least connections spread the flood evenly across every backend, while IP hash — precisely because it's deterministic — can end up concentrating a disproportionate share of the flood onto whichever backends the flood's source hashes land on. A load balancer alone doesn't stop a DDoS; rate limiting and upstream filtering do that. What the LB decides is how gracefully the pool degrades while it's happening.

Layer 4 vs. Layer 7 load balancing

This simulation models Layer 7 behaviour: the load balancer is aware of individual requests, can inspect them, and decides per-request where traffic goes. Real load balancers actually split into two distinct categories based on which layer of the network stack they operate at:

 Layer 4 (transport)Layer 7 (application)
SeesIP address and port onlyFull request: headers, path, cookies, body
Routing granularityPer TCP/UDP connectionPer HTTP request
Can route by URL pathNoYes (e.g. /api → service A, /static → service B)
OverheadVery low — just forwards packetsHigher — has to terminate and parse the request
Typical useRaw throughput, non-HTTP protocols, DDoS-scale trafficContent-aware routing, A/B testing, sticky sessions