Production engineering guide for load balancer algorithms covering patterns, implementation strategies, and operational best practices.
Load balancing distributes incoming network traffic across a pool of backend servers. It ensures high availability, improves response time, and enables horizontal scaling. This page details the core algorithms used in load balancers—how requests are routed, what decisions are made, and what happens when things go wrong. The focus is on the mechanics of routing, not on infrastructure setup or orchestration. The reader should be able to implement, debug, and tune any of these algorithms using standard tools and protocols.
Round robin is the simplest load balancing algorithm: each request is assigned to the next server in a fixed list, cycling through the list on each new request.
It works over HTTP, TCP, or UDP, and is implemented in all major load balancers: nginx, HAProxy, Envoy, and AWS ELB.
In nginx, round robin is enabled by default. To configure a server group:
upstream backend {
server 10.0.0.10:8080;
server 10.0.0.11:8080;
server 10.0.0.12:8080;
}
server {
location / {
proxy_pass http://backend;
}
}
Each request to / is routed to 10.0.0.10, then 10.0.0.11, then 10.0.0.12, then back to 10.0.0.10, and so on.
down keyword: upstream backend {
server 10.0.0.10:8080 weight=2;
server 10.0.0.11:8080 down;
server 10.0.0.12:8080;
}
Weighted round robin extends basic round robin by assigning a weight to each server, determining how many requests it receives per cycle.
The algorithm maintains a counter per server. Each time a request is assigned, the counter is incremented by the server’s weight. The server with the highest counter is selected, and its counter is reset to zero (or decremented by the total sum of all weights).
HAProxy supports weighted round robin via the weight directive:
backend web-servers
balance roundrobin
server web1 10.0.0.10:8080 weight 3 maxconn 100
server web2 10.0.0.11:8080 weight 2 maxconn 50
server web3 10.0.0.12:8080 weight 1 maxconn 25
With this configuration:
web1 receives 3 of every 6 requests,web2 receives 2,web3 receives 1.maxconn limit is reached. HAProxy stops sending new connections to it, but continues to route requests to it via existing connections.backup, it only receives traffic when all primary servers are full.Least connections selects the server with the fewest active connections. It is especially effective when connection durations vary significantly across backends.
In nginx, use least_conn:
upstream backend {
least_conn;
server 10.0.0.10:8080;
server 10.0.0.11:8080;
server 10.0.0.12:8080;
}
The load balancer tracks the number of active connections per server and routes each new request to the one with the smallest count.
ESTABLISHED state.conn_timeout and check directives to detect failed servers.maxconn to avoid overloading a server: server 10.0.0.10:8080 maxconn 100;
check to monitor server health: server web1 10.0.0.10:8080 check interval 5000 rise 2 fall 3
This sends a health check every 5 seconds. A server is marked up after two successful checks, down after three failures.
Least time combines response time and connection count into a single metric: least_time(response_time, active_connections).
The algorithm selects the server with the smallest response_time + (active_connections / weight), where weight is the server’s capacity.
Envoy supports least time via the least_request load balancing strategy:
clusters:
- name: backend
type: STRICT_DNS
lb_policy: LEAST_REQUEST
load_assignment:
cluster_name: backend
endpoints:
- lb_endpoints:
- endpoint:
address:
socket_address:
address: 10.0.0.10
port_value: 8080
- endpoint:
address:
socket_address:
address: 10.0.0.11
port_value: 8080
- endpoint:
address:
socket_address:
address: 10.0.0.12
port_value: 8080
Envoy measures:
It computes the least time metric and selects the server with the smallest value.
x-envoy-upstream-service-time header to record the time taken by the backend to process a request.x-envoy-upstream-service-time, the load balancer uses a default value, leading to suboptimal routing.Random load balancing selects a server uniformly at random from the pool.
It is simple to implement and works well when:
In HAProxy, use balance random:
backend web-servers
balance random
server web1 10.0.0.10:8080
server web2 10.0.0.11:8080
server web3 10.0.0.12:8080
Each new request is assigned to a server chosen via a random number generator.
server web1 10.0.0.10:8080 weight 3
server web2 10.0.0.11:8080 weight 2
server web3 10.0.0.12:8080 weight 1
This generates a probability distribution where web1 is selected 3/6 = 50% of the time, web2 33%, web3 17%.
Session affinity routes all requests from a client to the same backend server. It is implemented using:
The load balancer computes a hash of the client’s IP address and uses it to select a server.
In nginx:
upstream backend {
ip_hash;
server 10.0.0.10:8080;
server 10.0.0.11:8080;
server 10.0.0.12:8080;
}
The ip_hash directive uses the first 32 bits of the client’s IP address to compute a hash, which maps to a server.
The load balancer sets a cookie on the first request and uses it on subsequent requests.
Example:
GET /api/usersSet-Cookie: balancer=web1; Path=/Cookie: balancer=web1The load balancer reads the cookie and routes the request to the specified server.
The load balancer reads a header (e.g., X-Client-ID) and uses it as the key.
In HAProxy:
balance source
hash-type consistent
server web1 10.0.0.10:8080
server web2 10.0.0.11:8080
The source algorithm uses the client’s IP as the key, and hash-type consistent improves performance when the server list changes.
ip_hash with least_conn to balance load while maintaining affinity.No algorithm is perfect. The choice depends on the characteristics of the backend, the traffic pattern, and the tolerance for session loss.
This page was rewritten on 18 October 2026. It replaced a templated version that was not specific to its own title. How these pages are written and checked. If anything here is wrong, tell us at [email protected] and we will correct it.
We use cookies for analytics (Google Analytics) and advertising (Google AdSense) to improve your experience and support free content. Privacy Policy