Nginx Upstream Timed Out (110: Connection Timed Out): Reading the Log Line and Fixing It
The error log line upstream timed out (110: Connection timed out) means nginx, acting as a proxy, gave up waiting on your upstream, the application server behind it, after one of its timeout limits expired. The 110 is the operating system's error number for a timed-out connection; the visitor, meanwhile, receives a 504 Gateway Timeout. Nginx is reporting that it asked your application for a response and ran out of patience before getting one.
The line is more precise than it first appears, because its second half names the phase that failed, and the phase names the timer, and the timer names the fix. Nginx runs three separate clocks against an upstream, each with its own directive and each defaulting to 60 seconds, and this article decodes which clock fired from the exact wording in your log, then walks the fixes in the order that lasts: repairing the slow upstream first, raising the right timeout second and judiciously, and understanding how this error relates to its log-file neighbor, the nginx 499, which is the same slowness observed from the client's side of the glass.
Three timers, one log line
When nginx proxies a request it must connect to the upstream, send the request, and read the response, and each phase has its own limit. The connect phase is governed by proxy_connect_timeout, the sending phase by proxy_send_timeout, and the waiting-for-an-answer phase by proxy_read_timeout, with all three defaulting to 60 seconds; for PHP-FPM behind fastcgi, the same roles belong to the fastcgi family, with fastcgi_read_timeout as the one that matters most in practice.
The log line's suffix tells you which phase died. While connecting to upstream means the TCP connection itself never completed: the app server is down, unreachable, or refusing at the network level, and the request never reached your code at all. While reading response header from upstream is by far the most common variant and means the opposite: the connection worked, the request was delivered, and your application held it past the read timeout without producing a response. The first variant is an availability problem, debug it like the connection failures earlier in this series; the second is a performance problem, and the rest of this article is about it.
Fixing the upstream before the timeout
Identify what the request was doing. The log line includes the request URL and the upstream address. Pull the slow endpoints from the pattern of these errors, and you will usually find the familiar suspects: unindexed database queries, synchronous calls to slow third-party APIs, report and export routes doing batch work inline.
Check the worker pool for exhaustion. With PHP-FPM and similar pools, a saturated pool queues incoming requests until a worker frees up, and queue time counts against nginx's clock. If timeouts arrive in bursts at traffic peaks, inspect the pool's status and its max-children ceiling; a pool sized for last year's traffic produces this exact signature.
Profile and repair the slow work. Slow-query logs, execution plans, and missing indexes solve more upstream timeouts than any configuration change, and long-running jobs belong in background queues with a fast acknowledgment, the same restructuring that prevents the 120-second timeouts behind Cloudflare error 524.
Watch the trend, not the incident. Endpoints drift toward timeouts as data grows. Response-time percentiles per endpoint, the discipline laid out in Odown's guide to API latency, show the approach to the 60-second line weeks before the first 504.
Raising the timeout, judiciously
Sometimes the work is legitimately long, a big report for an internal tool, a known-slow partner API you cannot fix, and the right move is a larger budget. Do it narrowly: raise proxy_read_timeout, or fastcgi_read_timeout for PHP, inside the specific location block that needs it, rather than server-wide, so one slow route does not license slowness everywhere. Keep the whole chain consistent while you are there, because a raised nginx timeout accomplishes nothing if a load balancer in front still quits at 60 seconds, and it produces 499s instead if the client gives up first; the ordering rule is that each outer layer should wait at least as long as everything behind it.
And be honest about what a raise buys. Doubling 60 to 120 seconds does not make a 90-second query acceptable; it makes users wait 90 seconds, which most will not, converting your 504s into abandonments. Timeout increases are for work whose duration is intended, not work whose duration is a surprise.
Common mistakes in fixing upstream timeouts
Raising all three timers at once. Only one phase fired, and the log names it. Raising connect timeouts for a read-phase problem changes nothing except your ability to reason about the config later.
Raising timeouts globally. A server-wide 300-second read timeout turns every stuck request into a five-minute resource hold. Scope increases to the location that earned them.
Missing the connect-phase variant. While connecting to upstream means the app server is unreachable, a dead process, wrong upstream address, or firewall, and no read-timeout tuning applies. Read the suffix before touching a directive.
Forgetting the layer in front. If a load balancer or CDN sits before nginx with a shorter limit, users see its timeout no matter what nginx allows. Fix the chain outside-in.
Treating the 504 as the incident. The 504 is the receipt; the incident is the endpoint that slowed down. Without latency monitoring per endpoint, the same receipt will keep arriving.
FAQ
What is the default nginx upstream timeout?
Sixty seconds for each phase: proxy_connect_timeout, proxy_send_timeout, and proxy_read_timeout, with the fastcgi equivalents matching. In practice the read timeout is the one requests actually hit, because it covers the time your application spends producing an answer.
What does the 110 in the error mean?
It is the operating system's error number for a connection that timed out, which nginx passes through into its log. It confirms the failure was a timeout rather than a refusal or reset, nothing more.
Why do visitors see a 504 when this line appears?
Because nginx, having given up on the upstream, must tell the client something, and 504 Gateway Timeout is the standard code for a proxy whose upstream did not answer in time. The log line and the 504 are two views of the same event.
Should I just increase proxy_read_timeout?
Only for routes whose long duration is intentional, and only in their location block, with the outer layers extended to match. For everything else, the increase merely postpones the timeout while lengthening how long users and workers stay stuck.
Closing thought
This log line is unusually generous: it names the upstream, the request, the failed phase, and, through the phase, the exact directive involved. Read the suffix first, connecting means unreachable, reading means slow, then spend the effort where it compounds: fixing the slow work, sizing the worker pool, and scoping any timeout increase to the routes that genuinely earn it, with the chain ordered outside-in.
Upstream timeouts are also the loudest late symptom of a quiet trend, an endpoint's latency climbing toward a fixed limit. Odown monitors your endpoints' response times from 17 locations with thresholds you choose, so the route drifting from four seconds toward sixty shows up as an alert while it is a performance ticket, not a page of 504s, and its API monitoring checks the same routes for correctness, not just speed, on every pass.



