Error fix · Server errors

nginx "no live upstreams while connecting to upstream" Fix

nginx logs no live upstreams when every server in an upstream block is marked failed. Learn why it happens and how to tune max_fails and fail_timeout.

Error messageno live upstreams while connecting to upstream

By SiteDownCheck Editorial · Updated October 14, 2026 · 4 min read

This error means nginx has a group of backend servers defined in an upstream block, and right now it considers every one of them unavailable. Visitors get a 502 Bad Gateway, and your error log shows:

2026/10/08 09:14:02 [error] 1823#1823: *4471 no live upstreams while connecting to upstream, client: 203.0.113.7, server: example.com, request: "GET /api/orders HTTP/1.1", upstream: "http://backend/api/orders", host: "example.com"

The important word is considers. nginx keeps a passive health record for each upstream server. When a server fails max_fails times within fail_timeout, nginx stops sending it traffic for the next fail_timeout period. If all servers are in that state at the same moment, nginx has nobody left to try and logs this line instead of a connection error. So the message is a symptom. The real failure is in the log lines just before it.

Find the original failure first

Look at the errors that precede the first "no live upstreams" line:

sudo grep -n -B20 -m1 "no live upstreams" /var/log/nginx/error.log

You will usually see one of these just above it:

  • connect() failed (111: Connection refused) while connecting to upstream: the backend process is not listening. See nginx connect() failed 111.
  • upstream timed out (110: Connection timed out): the backend is up but too slow. See nginx upstream timed out.
  • upstream prematurely closed connection: the backend crashed or was restarted mid-request.
  • recv() failed (104: Connection reset by peer): the backend dropped the connection, often an app server hitting a memory or worker limit.

Fix that underlying failure and the marker clears by itself once fail_timeout expires.

How the passive health logic works

Here is a typical upstream block with the defaults written out:

upstream backend {
    server 10.0.0.11:8080 max_fails=1 fail_timeout=10s;
    server 10.0.0.12:8080 max_fails=1 fail_timeout=10s;
}

The defaults are max_fails=1 and fail_timeout=10s. That is aggressive: a single failed request marks a server unavailable for 10 seconds. With two backends, two unlucky failures within a few seconds can take out the whole group, even though both servers are healthy. A traffic spike that makes both slow for a moment is enough.

What counts as a failure is controlled by proxy_next_upstream (or fastcgi_next_upstream, uwsgi_next_upstream and so on). By default, connection errors and timeouts count. An HTTP 500 or 502 returned by the backend does not count unless you add http_500 or http_502 to the list.

Fix 1: make the failure marking less twitchy

Raise the tolerance so a short blip does not eject healthy servers:

upstream backend {
    server 10.0.0.11:8080 max_fails=3 fail_timeout=30s;
    server 10.0.0.12:8080 max_fails=3 fail_timeout=30s;
    keepalive 16;
}

Setting max_fails=0 disables the accounting for that server, so nginx always tries it. That trades protection for availability and is reasonable when you have a separate health-checking load balancer in front.

Fix 2: add a backup server

A server marked backup only receives traffic when the primary servers are unavailable:

upstream backend {
    server 10.0.0.11:8080;
    server 10.0.0.12:8080;
    server 10.0.0.99:8080 backup;
}

A static "we are having trouble" page served from that backup is better than a bare 502.

Fix 3: check the backend itself

From the nginx host, test each backend directly and bypass nginx entirely:

curl -sS -o /dev/null -w "%{http_code} %{time_total}s\n" http://10.0.0.11:8080/health
curl -sS -o /dev/null -w "%{http_code} %{time_total}s\n" http://10.0.0.12:8080/health
ss -ltnp | grep -E ':8080\b'

If curl hangs or refuses, the application process is the problem. Check its logs, restart it, and look for out-of-memory kills with sudo journalctl -k | grep -i "out of memory". If the backends answer fine from the nginx host but not through nginx, look at firewall rules, SELinux on RHEL-family systems (setsebool -P httpd_can_network_connect 1), and DNS names in the upstream block. Hostnames in server lines are resolved when nginx starts, so a backend that changed IP needs a reload.

Fix 4: validate and reload

sudo nginx -t
sudo systemctl reload nginx

nginx -t checks syntax; a reload applies the change without dropping connections. After a reload, all failure counters reset, which also makes it a quick way to confirm the diagnosis: if the error disappears and the backends are healthy, it was the marking logic.

Confirm it is fixed

Watch the error log while sending real traffic: sudo tail -f /var/log/nginx/error.log. Then check from outside with the HTTP Status Checker and confirm the backend ports with the Port Checker if they are publicly reachable. An uptime monitor on a URL that touches the backend will tell you the next time both servers drop out together. For wider context, read nginx 502 and 504 timeout tuning and load balancer health checks.

Next steps

FAQ

How long does nginx keep a server marked as failed?

For fail_timeout, which defaults to 10 seconds. After that period nginx tries the server again, and one success restores it fully.

Does open source nginx do active health checks?

No. Open source nginx only does passive checks through max_fails and fail_timeout. Active health checks are a feature of NGINX Plus; check its current documentation.

Why does it only happen with multiple backends?

With a single server in the group, nginx ignores max_fails and fail_timeout, so you get connection errors instead of this message.

Will reloading nginx fix it?

It clears the failure counters, so it can hide the problem briefly. If the backends are still failing, the servers will be marked again within seconds.

Get notified when this fix updates

Plus occasional practical tips on uptime and monitoring, nothing else. Unsubscribe anytime.

This page is general information written by our editorial team and updated when documentation changes. Servers and providers differ, so test changes safely first. See our editorial policy and disclaimer.