Load Balancing

A load balancer distributes incoming traffic across multiple backend servers, so no single server is overwhelmed and the system can scale and stay available. It's the linchpin of running anything at scale: the moment you need more than one server — for capacity or for redundancy — you need something in front of them deciding where each request goes. That something is a load balancer, and it's simultaneously how you scale horizontally and how you survive a server failure without downtime.

The load balancer does two jobs at once: spread the load (so you can add servers to handle more traffic) and route around failures (health-check backends and stop sending traffic to dead ones). Understanding the layer it operates at (L4 vs L7), the algorithm it uses to pick a server, and how it handles health checks and sessions covers the essentials for designing a resilient, scalable system.

TL;DR

Quick Example

The load balancer sits in front, fanning requests out to healthy backends:

Why Load Balancing Matters

L4 vs L7

Load balancers operate at different network layers (see TCP/IP):

Most web apps use an L7 load balancer (or both: L4 for raw throughput, L7 for routing). See Cloud Networking for cloud load balancers.

Balancing Algorithms

Least connections is a strong default for varied request durations; round robin is simplest; IP hash provides stickiness when needed.

Health Checks & Sessions

Best Practices

Common Mistakes

Stateful servers with naive balancing

No health checks

FAQ

What's the difference between L4 and L7 load balancing?

Layer 4 load balancing operates at the transport layer, routing traffic by IP address and port without looking at the content of the request. It's very fast and works for any protocol, but it can't make content-based decisions. Layer 7 load balancing operates at the application layer, inspecting the HTTP request — URL path, host, headers, cookies — so it can do path-based routing ("/api → API servers"), host-based routing, SSL termination, and other content-aware logic, at a modest performance cost. Most web applications use L7 for its flexibility; high-throughput or non-HTTP workloads may use L4, and some architectures combine both.

How does a load balancer improve reliability, not just scale?

Through health checks and failover. The balancer continuously probes each backend (typically hitting a /health endpoint), and when a server fails the check, it's automatically removed from rotation so no traffic reaches the dead server — users never notice. When the server recovers, it's added back. This turns a server crash from an outage into a non-event, and it enables zero-downtime deploys (drain a server, update it, return it to rotation). Combined with spreading servers across availability zones, load balancing is the foundation of high availability for the application tier, not just a tool for distributing load.

What balancing algorithm should I use?

It depends on your traffic. Round robin (each server in turn) is simplest and fine when requests are roughly uniform. Least connections (send to the server with the fewest active connections) is a strong default when request durations vary, since it avoids piling work on a server still busy with long requests. Weighted variants account for servers of different capacity. IP hash provides stickiness (same client → same server) when you need it. For most web apps, least connections or round robin works well; choose based on whether your requests are uniform or highly variable in duration.

What are sticky sessions and should I use them?

Sticky sessions (session affinity) make the load balancer route a given user's requests to the same backend server every time, usually so that server's in-memory session data stays accessible. The better alternative is to keep servers stateless — store session state in a shared external store (Redis, a database) so any server can handle any request. Stateless is more resilient (a server failing doesn't log users out or lose their session) and makes scaling and deploys cleaner. Use sticky sessions only when you genuinely can't externalize state; they complicate failover and can unbalance load. Stateless-with-shared-store is the recommended default.

Related Topics

References