Load balancing — algorithms and health checks
"Put a load balancer in front of it" is step one. Which algorithm it uses to pick a server, and how it knows a server is actually healthy, are the decisions that determine whether it actually helps.
3 min read
What a load balancer is actually for
A load balancer sits between clients and a pool of backend servers, and for every incoming request, decides which server handles it. This is the mechanism that makes horizontal scaling possible at all — without it, clients would need to somehow know about and choose between individual server addresses themselves, and there'd be no way to route around a server that crashed.
Round robin — the simplest algorithm, and its blind spot
Round robin cycles through servers in fixed order, sending each new request to the next one in line. It's simple and works well when every server has equal capacity and every request costs roughly the same to handle — its blind spot is exactly when those assumptions break: if one server is slower, or some requests are far more expensive than others, round robin keeps sending equal shares of traffic to unequal capacity, overloading the slower server just as fast as the others.
Least connections — accounting for request cost, not just count
Instead of a fixed rotation, least-connections routing sends each new request to whichever server currently has the fewest active connections — a proxy for "how busy is this server right now," which adapts automatically to servers handling requests at different speeds or requests that take wildly different amounts of time to finish. A server stuck on a few slow requests naturally receives fewer new ones, since its active-connection count stays elevated, without the load balancer needing to know why it's busy.
Weighted variants — accounting for unequal server capacity
Both algorithms have weighted versions: weighted round robin and weighted least connections assign each server a weight reflecting its actual capacity (a server with twice the CPU gets weight 2, receiving roughly twice the traffic share), rather than assuming every server in the pool is identical. This matters in real deployments where the server pool isn't homogeneous — during a gradual hardware upgrade, or when cheaper and more powerful instance types are deliberately mixed for cost reasons.
Health checks: the mechanism that makes any of this safe
None of these algorithms are safe to run without health checks — the load balancer periodically pings each server (an HTTP request to a dedicated /health endpoint is the common pattern) and stops routing traffic to any server that fails to respond correctly, automatically removing it from rotation:
Without health checks, a crashed or overloaded server keeps receiving its normal share of traffic indefinitely, actively making the outage worse for every user routed to it — the load balancer has no way to know it should stop, so it doesn't. This is what actually gives horizontal scaling its resilience benefit: an instance failing doesn't take the whole service down, because traffic reroutes automatically to instances that are still healthy.
Sticky sessions — the feature that fights statelessness
Some setups need session affinity (sticky sessions): once a client's first request lands on a specific server, every subsequent request from that same client is routed to that same server, usually via a cookie the load balancer sets. This is genuinely useful for session data stored in server memory rather than a shared store — but it directly works against the stateless-server assumption that makes horizontal scaling clean in the first place, and it creates uneven load (a server holding many active "sticky" sessions can't shed that traffic to less-busy servers). Externalizing session state to a shared store (like Redis) instead of relying on sticky sessions is usually the better trade, when it's an option.
Further reading
Check your understanding
A quick comprehension check — not tracked, not graded, just for you.
1. What's the blind spot of round-robin load balancing?
2. How does least-connections routing adapt to servers handling requests at different speeds, without knowing why a server is slow?
3. What happens to a crashed server if a load balancer has no health checks configured?
4. Why do sticky sessions work against the benefits of horizontal scaling?