Not all load balancing algorithms are equal. The right choice depends on your traffic patterns, backend capabilities, and consistency requirements.
Round Robin
The default. Requests go to each server in turn.
Nginx:
| |
HAProxy:
| |
When to use:
- All backends have identical capacity
- Requests have similar processing time
- No session affinity needed
When to avoid:
- Backends have different specs (CPU, RAM)
- Some requests are much heavier than others
Weighted Round Robin
Like round-robin, but servers get proportional traffic based on weight.
Nginx:
| |
When to use:
- Mixed server capacity (some servers more powerful)
- Gradual traffic shifting (canary deployments)
- Cost optimization (send more to cheaper instances)
| |
Least Connections
Route to the server with fewest active connections.
Nginx:
| |
HAProxy:
| |
When to use:
- Long-lived connections (WebSockets, database proxies)
- Highly variable request duration
- Some requests much heavier than others
When to avoid:
- Very short requests (overhead of tracking connections)
- All requests take similar time (round-robin is simpler)
Weighted Least Connections
Combines weights with connection counting:
| |
The algorithm considers connections / weight ratio, so a server with weight=5 and 10 connections (ratio=2) beats a server with weight=2 and 6 connections (ratio=3).
IP Hash (Source Affinity)
Same client IP always goes to same server:
Nginx:
| |
HAProxy:
| |
When to use:
- Session affinity without cookies
- Caching layers (same content on same server)
- Stateful applications that can’t share state
When to avoid:
- Clients behind NAT (many users share one IP)
- Need to drain servers gracefully (sticky users won’t move)
Consistent Hashing
Advanced hashing that minimizes disruption when servers change:
| |
When a server is added or removed, only 1/n of requests remap (not all of them).
When to use:
- Caching proxies (maximize cache hits)
- Sharded data stores
- Any system where “same request → same server” matters
| |
Random with Two Choices
Pick two servers randomly, choose the one with fewer connections:
HAProxy:
| |
Surprisingly effective—nearly as good as least-connections with less overhead. Good for very high throughput scenarios.
Health Checks
All algorithms should include health checks:
Nginx (passive):
| |
Nginx Plus (active):
| |
HAProxy:
| |
Graceful Degradation
Mark servers as backup or slowly drain them:
| |
Draining a server:
| |
Existing connections to the down server continue until complete.
Layer 4 vs Layer 7
Layer 4 (TCP/UDP):
- Faster (no HTTP parsing)
- Works for any protocol
- Limited routing options
| |
Layer 7 (HTTP):
- Content-based routing
- Can modify requests/responses
- More features (caching, compression)
| |
Quick Reference
| Algorithm | Best For | Avoid When |
|---|---|---|
| Round Robin | Equal servers, uniform requests | Mixed capacity |
| Weighted | Mixed capacity, canary deploys | All servers equal |
| Least Conn | Long/variable requests | Short uniform requests |
| IP Hash | Session affinity | NAT, server changes |
| Consistent Hash | Caching, sharding | No locality benefit |
| Random(2) | High throughput | Need determinism |
My Recommendations
- Start with round-robin — simplest, works for most cases
- Add weights when server capacity varies
- Switch to least-conn when request duration varies significantly
- Use consistent hash for caching layers
- Avoid IP hash unless you have no other option for session affinity
Always combine with proper health checks. A perfect algorithm sending traffic to a dead server is worse than a simple algorithm with good health checks.
The best load balancer is one you don’t have to think about. Choose the simplest algorithm that meets your needs.