Load Balancing: A Visual Guide to Algorithms

Every load balancing diagram you’ve seen is lying to you.

Not maliciously. Just… optimistically. This post shows you what load balancing actually looks like in practice, with live simulations you can watch and control.

The First Lie: “Perfect Balance”

Load balancing is usually explained like this: “We evenly distribute traffic across servers.”

That idea is comforting. It is also mostly fictional. In real systems:

  • requests have different costs
  • servers have different speeds
  • traffic arrives in bursts

Visualizing the Problem

Let’s start simple: one load balancer sending requests to a single server. Requests are green dots. They shrink as the server processes them.

Single Server — Happy Path
Load Balancer
Completed: 0
Dropped: 0
Time: 0s
At 1 RPS, a single server handles traffic comfortably. Each request arrives, gets processed, and completes before the next one arrives.

For many websites, this works fine. But what happens when traffic increases?

Single Server — Overloaded
Load Balancer
Completed: 0
Dropped: 0
Time: 0s
At 3 RPS, the queue fills up. When it's full, requests get dropped. We need more servers.

Round Robin

The simplest solution: add more servers and send requests to each one in turn. This is called round robin.

Round Robin — Uniform Load
Load Balancer
Completed: 0
Dropped: 0
Time: 0s
With identical servers and uniform requests, round robin distributes load evenly. No more dropped requests.

Beautiful. Each server gets the same number of requests, queues stay balanced. This is why round robin is the default in nginx.

When Round Robin Breaks

In the real world, requests aren’t equally expensive. An image resize takes longer than a health check. Let’s add some variance:

Round Robin — Variable Request Costs
Load Balancer
Completed: 0
Dropped: 0
Time: 0s
Now requests have different costs (some shrink slower). Watch how some servers get unlucky with expensive requests and their queues back up.

Round robin balances requests, not work. A server that gets three expensive requests in a row will fall behind.

It gets worse with heterogeneous servers:

Round Robin — Mixed Server Power
Load Balancer
Completed: 0
Dropped: 0
Time: 0s
Servers have different processing speeds (darker = faster). Round robin sends equal traffic to each, overwhelming the slower servers.

The Assumption

Round robin assumes all servers are equal and all requests are equal. The moment either assumption breaks, you get imbalance.

The fix? Weighted round robin. If a server is 3x faster, give it 3x the traffic:

Weighted Round Robin
Load Balancer
Completed: 0
Dropped: 0
Time: 0s
Faster servers (darker, lower latency) receive proportionally more requests. Watch how the queues stay more balanced.

Request Queues

You might have noticed the servers have queues (the vertical bars above them). Without queues, any request that arrives while the server is busy gets dropped immediately.

Queues let us absorb bursts, but they’re a trade-off: we drop fewer requests, but at the cost of higher latency. A request sitting in a queue isn’t being processed—it’s waiting.

Least Connections

What if instead of blindly rotating, we sent each request to the server with the shortest queue?

Least Connections
Load Balancer
Completed: 0
Dropped: 0
Time: 0s
Always routes to the server with the shortest queue. Watch how it naturally adapts to both request cost variance and server power differences.

Notice how the queues stay much more balanced? Least connections cuts through uncertainty by tracking actual work in progress.

The Caveat

Least connections counts connections, not work. A server holding 10,000 idle WebSockets looks busy but isn’t. For request/response workloads though, it’s excellent.

The Power of Two Choices

What if instead of checking every server (expensive) or picking one at random (chaotic), we did something in between?

Idea: Pick 2 random servers. Send the request to whichever has less load.

Algorithm Comparison: Variance
Random Selection
Peak: 0
Power of Two Choices
Peak: 0

Observe the 'Jagged Skyline' effect on the left (hotspots) versus the 'Smooth Horizon' on the right. Power of Two Choices aggressively flattens variance.

Power of Two Choices
Load Balancer
Completed: 0
Dropped: 0
Time: 0s
Pick two random servers, choose the less loaded one. Exponentially reduces maximum load compared to pure random selection.

Why It Works

The math is beautiful: with random selection, the most loaded server has O(log n / log log n) items. With two choices, it drops to O(log log n). That’s an exponential improvement from one extra comparison.

Algorithm Comparison

Let’s put them head to head. Same high-variance scenario, different algorithms. Watch how they handle the chaos:

Round Robin
Load Balancer
Completed: 0
Dropped: 0
Time: 0s
Least Connections
Load Balancer
Completed: 0
Dropped: 0
Time: 0s

Notice the difference in dropped requests and queue balance. Least connections adapts to the actual work being done.

Real-Time Benchmark

Watch all four algorithms compete in real-time. The simulation runs identical workloads through each strategy simultaneously, tracking latency, drop rate, and throughput.

Algorithm Benchmark
Time: 0.0s / 10s
Click "Run Benchmark" or select a scenario to start
Seed: 12345

Performance Metrics

The simulations above show behavior in real-time, but let’s look at the aggregate data. These charts show what happens over thousands of requests:

Response Time Over Time

Round Robin
Weighted RR
Least Connections

Least Connections maintains lower response times during traffic spikes (30-40s) by routing to less busy servers.

Response Time Distribution

Round Robin
Least Connections

Least Connections produces a tighter distribution with more requests completing quickly, while Round Robin has a longer tail of slow requests.

Throughput Comparison

Round Robin
Weighted RR
Least Connections

Under increasing load, Least Connections maintains higher throughput by efficiently utilizing server capacity.

Hash-Based Load Balancing

Sometimes you need requests from the same user to hit the same server. Session affinity, caching, stateful connections.

Idea: Hash something stable (user ID, session ID, IP) and use it to pick a server deterministically.

The Celebrity Problem

If you hash by user ID and @elonmusk tweets, the server owning that hash bucket melts. Then health checks fail, traffic shifts, the celebrity moves to the next node, and that node melts too.

When to Use Hashing

Hash-based routing is great for cache locality and session affinity. Just make sure you have a fallback for hot keys.

Choosing an Algorithm

  • Uniform traffic, identical servers → Round Robin
  • Variable request costs → Least Connections
  • Large server pools → Power of Two Choices
  • Session affinity needed → Consistent Hashing

Playground

Now it’s your turn. Experiment with different algorithms and parameters. Try to break things.

Playground
Load Balancer
Completed: 0
Dropped: 0
Time: 0s
Adjust the parameters above to see how different algorithms handle various scenarios. Try increasing RPS until requests start dropping, or add server power variance to see how algorithms adapt.

Conclusion

The best load balancing algorithm is often “buy more servers.” The second best is “fix your database queries.”

If you are desperately tuning load balancing algorithms to survive, you probably don’t have a routing problem. You have a capacity problem.

Load balancers distribute traffic. They do not create headroom.

Newsletter

System design patterns, delivered.

Join 4,000+ engineers. No spam, just deep dives into infrastructure, algorithms, and frontend architecture.

Unsubscribe at any time.