NGINX as Load Balancer
New to NGINX? Start by reading NGINX introduction.
flowchart LR
Client1 -- request --> LoadBalancer
Client2 -- request --> LoadBalancer
Client3 -- request --> LoadBalancer
Client4 -- request --> LoadBalancer
ClientN -- request --> LoadBalancer
LoadBalancer -- hash(ip)%3 --> Backend1
LoadBalancer -- hash(ip)%3 --> Backend2
LoadBalancer -- hash(ip)%3 --> BackendN
Load Balancing
instead of forwarding requests to a single backend server, NGINX can distribute requests across multiple backend servers. This is called load balancing.
NGINX / | \ / | \ v v v Server 1 Server 2 Server 3define backend servers inside an
upstreamblock:upstream backend { server localhost:8000; server localhost:8001; server localhost:8002; } server { listen 8090; location / { proxy_pass http://backend; } }
Load Balancing Methods
Round Robin — the default method; requests are distributed sequentially across the servers:
upstream backend { server localhost:8000; server localhost:8001; server localhost:8002; }Request 1 -> Server 1 Request 2 -> Server 2 Request 3 -> Server 3 Request 4 -> Server 1 ...Weighted Round Robin — give more powerful servers a larger
weightso they receive more requests:upstream backend { server localhost:8000 weight=3; server localhost:8001 weight=1; }Server 1 -> ~75% of requests Server 2 -> ~25% of requestsIt is similarly possible to use weights with the least-connected and ip-hash load balancing in the recent versions of nginx.
Least Connections — send a new request to the server currently handling the fewest active connections:
upstream backend { least_conn; server localhost:8000; server localhost:8001; server localhost:8002; }Useful when requests can have significantly different processing times, because simply distributing an equal number of requests may not distribute the actual workload equally.
IP Hash — use the client’s IP address to determine which backend receives the request:
upstream backend { ip_hash; server localhost:8000; server localhost:8001; server localhost:8002; }This can be useful when requests from the same client should generally reach the same backend, such as applications that maintain local session state.
NGINX also supports generic hash and random load-balancing methods:
upstream backend { hash $request_uri; server localhost:8000; server localhost:8001; }upstream backend { random; server localhost:8000; server localhost:8001; }these methods are less commonly needed for a basic setup, so normally Round Robin, Weighted Round Robin, Least Connections, and IP Hash are the important ones to know.
Which One to Choose?
| Method | When to use |
|---|---|
| Round Robin | General-purpose load balancing when backend servers have roughly similar capacity |
| Weighted Round Robin | Backend servers have different capacities and more powerful servers should handle more traffic |
| Least Connections | Requests have varying processing times or some requests remain connected for much longer |
| IP Hash | The same client should generally reach the same backend |
| Generic Hash | You need consistent routing based on a specific value such as URI, client information, or another variable |
| Random | You want randomized distribution and don’t have a specific routing requirement |
Tip
Start with Round Robin unless you have a reason to choose something else. Use Weighted Round Robin when servers have different capacities, Least Connections when connection duration varies significantly, and IP Hash when client affinity is important.
About Health Checkes (Bonus)
NGINX can perform passive, or in-band, health checking of servers in an upstream group. It monitors failures while processing normal client requests. When a server repeatedly fails to handle requests successfully, NGINX temporarily treats it as unavailable and reduces the chance of sending additional requests to it.
The max_fails parameter controls how many failed communication attempts are allowed within the fail_timeout period before a server is considered unavailable. Its default value is 1. Setting max_fails to 0 disables passive health checking for that server.
fail_timeout serves two purposes: it defines the time window used to count failures and specifies how long NGINX keeps the server in a failed state. Once that period expires, NGINX can begin sending normal client requests to the server again. If the server responds successfully, it is treated as healthy and continues receiving traffic.
Referenes
NGINX docs on HTTP Load Balancing -> https://nginx.org/en/docs/http/load_balancing.html