Nginx Load Balancer: How to Set It Up (Round Robin, Least Connections and More)
Nginx is one of the most common load balancers on the web. With a few lines of config it spreads traffic across several application servers, skips servers that fail, and keeps the site up while you deploy or reboot one of them.
Basic Setup
Define the backend servers in an upstream block (inside http, usually in a site file) and proxy to it:
upstream app_servers {
server 10.0.0.11:3000;
server 10.0.0.12:3000;
server 10.0.0.13:3000;
}
server {
listen 80;
server_name example.com;
location / {
proxy_pass http://app_servers;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
Test and reload with sudo nginx -t && sudo systemctl reload nginx (see testing and reloading Nginx config).
Load Balancing Methods
| Method | Directive | Best for |
|---|
| Round robin | (default) | Similar servers and similar requests |
| Least connections | least_conn; | Requests that take very different amounts of time |
| IP hash | ip_hash; | Keeping each visitor on the same server |
| Generic hash | hash $request_uri consistent; | Cache servers, where the same URL should hit the same node |
upstream app_servers {
least_conn;
server 10.0.0.11:3000;
server 10.0.0.12:3000;
}
Weights, Failover and Backup Servers
upstream app_servers {
server 10.0.0.11:3000 weight=3; # gets 3x the traffic
server 10.0.0.12:3000 max_fails=3 fail_timeout=30s; # skipped for 30s after 3 failures
server 10.0.0.13:3000 backup; # only used if the others are down
}
Open-source Nginx uses passive health checks: it notices failures on real requests and stops sending traffic to that server for fail_timeout. Active health checks (probing a URL on a schedule) are an NGINX Plus feature; with open-source Nginx, combine passive checks with your own monitoring.
Keepalive Connections to Backends
Reusing connections to the backends lowers latency under load:
upstream app_servers {
server 10.0.0.11:3000;
server 10.0.0.12:3000;
keepalive 32;
}
location / {
proxy_pass http://app_servers;
proxy_http_version 1.1;
proxy_set_header Connection "";
}
Sticky Sessions
If your app stores sessions in server memory, a visitor must keep hitting the same backend. ip_hash does this in open-source Nginx. The more robust fix is to store sessions in a shared place (Redis or the database) so any server can handle any request.
Load Balancing TCP or UDP
For databases or other non-HTTP services, use the stream module with the same upstream syntax, in a stream { } block outside http.
Troubleshooting
- 502 Bad Gateway: every backend refused or failed. See fixing 502 Bad Gateway.
- "no live upstreams" in the error log: all servers hit
max_fails; check that the apps are running. - Logins keep dropping: sessions are stored per server; use
ip_hash or shared session storage.
More codes are explained in common Nginx errors.
Frequently Asked Questions
Can Nginx be used as a load balancer?
Yes. The free, open-source version supports round robin, least connections, IP hash and generic hash balancing with passive health checks.
What is the default Nginx load balancing method?
Round robin: requests go to each server in turn, adjusted by any weights you set.
Does open-source Nginx support health checks?
Passive ones (max_fails and fail_timeout). Active health checks require NGINX Plus or an external monitor.
Need Room to Scale?
RackUp IT cloud and VPS hosting gives you dedicated resources to run your app servers, with the web layer managed for you.