When one app process isn’t enough, run several and let Nginx spread traffic across them. Declare an upstream pool at the http { } level, then proxy_pass to it by name.
upstream app_backend {
least_conn; # send to the server with fewest active connections
server 127.0.0.1:3001;
server 127.0.0.1:3002;
server 127.0.0.1:3003 weight=2; # gets ~2x the traffic
server 10.0.0.9:3000 backup; # only used if the others are down
keepalive 32; # pooled connections to the backends
}
server {
listen 80;
server_name example.com;
location / {
proxy_pass http://app_backend;
proxy_http_version 1.1;
proxy_set_header Connection ""; # required for upstream keepalive
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
Balancing methods (pick one, default is round-robin):
- round-robin (default) — even rotation.
least_conn;— fewest active connections; good for uneven request durations.ip_hash;— same client IP always hits the same backend (sticky sessions without shared state).
Other knobs:
weight=Nsends more traffic to bigger servers;backupmarks a standby.- Passive health: Nginx marks a server failed after
max_failserrors withinfail_timeout(e.g.server … max_fails=3 fail_timeout=15s;) and stops sending to it temporarily. keepalive 32;plusproxy_http_version 1.1and an emptyConnectionheader reuses backend connections — a big latency win. (Active health checks need Nginx Plus.)
sudo nginx -t && sudo nginx -s reload