upstream timed out (110: Connection timed out) in nginx error.log is not proof that a timeout value is simply too low. The following words identify the phase: connecting, sending or reading. Correlate time, upstream address and request ID with application logs before changing the relevant limit.

nginx is the hop between a client and an upstream. Code 110 indicates a system timeout, but the phase determines which directive matters. Waiting for a slow application response is different from failing to open a TCP connection. HTTP proxy and FastCGI use separate settings documented in the proxy module and FastCGI module. A CDN may emit yet another client-facing status; use the 5xx map to find the emitting hop.

Identify the phase from the error log
| error.log phrase | Phase | HTTP proxy directive | First check |
|---|---|---|---|
while connecting to upstream | Open connection | proxy_connect_timeout | Address, port, network and connection capacity |
while sending request to upstream | Send request | proxy_send_timeout | Whether upstream consumes the body |
while reading response header from upstream | Wait for headers | proxy_read_timeout | Application queue and execution time |
while reading upstream | Read body | proxy_read_timeout | Gaps between chunks |
For PHP-FPM, inspect the matching fastcgi_* settings and FPM queue. Read timeouts measure the gap between read operations, not a total response deadline. A stream may last longer than the setting while sending regular data; a long silent gap can trigger it.
Correlate logs with request timing
log_format upstream '$time_iso8601 request_id=$request_id $host "$request" '
'status=$status upstream=$upstream_addr '
'upstream_status=$upstream_status '
'connect=$upstream_connect_time header=$upstream_header_time '
'response=$upstream_response_time total=$request_time';
access_log /var/log/nginx/access_upstream.log upstream;
Run nginx -t before enabling the format; avoid exposing URL tokens in logs. $upstream_connect_time covers connection setup, $upstream_header_time reaches the header, and $upstream_response_time reaches completion. Retries can produce sequences of values, so match each address and status. The fields are documented in the nginx logging module.
Capture the outside curl timing breakdown and trace the same request ID inside. Fast application execution with slow connection setup suggests network or pool capacity. A 90-second database operation will remain slow after raising proxy_read_timeout to 120 seconds; inspect the query and dependencies. If idle connections are being closed, review keep-alive mismatches.
Change one limit with evidence
Capture the active config with nginx -T and measure response-time percentiles. Change the directive for the actual delayed phase and compare adjacent proxy deadlines. Waiting 120 seconds upstream is ineffective if a CDN ends the client request after 30. After reload, watch error rate, response time and occupied connections. Roll back if the tail worsens and fix the delayed dependency.
How we made this guide
The phase-to-directive mapping comes from official nginx docs. The log format is a diagnostic template, not a claim about a particular enterno.io incident. SerpAPI snapshots cover Google US and Yandex Moscow. Wordstat region 225 returned 11 for the exact Russian phrase and 12 for a broader one; search volume does not diagnose a timeout.
FAQ
Why did a read timeout show 504 instead of 502?
The particular gateway chooses the status. Check its logs and any outer proxy.
Can I immediately set 300 seconds?
You can, but it may conceal latency and hold connections. Measure normal execution and neighboring deadlines first.
Why did a download time out after headers?
A read timeout can trigger on a long gap between body chunks.
How do I distinguish network from slow application?
Correlate error-log phase, connect/header/response times and the application log by request ID.