Troubleshooting

Fix 504 Gateway Timeout errors on Nginx, PHP and app servers

Find why a request times out with 504 Gateway Timeout: slow PHP or database queries, mismatched proxy and FPM timeouts, CDN limits, and when to raise timeouts versus fix the code.

IntermediateLinux VPS3 min read

A 504 Gateway Timeout means the proxy waited for the backend and gave up. The backend is often still working, just too slowly. The fix is usually to make that request faster, and only sometimes to raise a timeout.

Before you start

  • Root access to the VPS and the URL and time of the error.
  • Know your chain: browser → (CDN) → Nginx → PHP-FPM, or Nginx → Node/Python app server.

Confirm where the timeout happens

Nginx logs it in /var/log/nginx/error.log:

upstream timed out (110: Connection timed out) while reading response header from upstream

If Nginx shows nothing but users see a Cloudflare-branded 504/524 page, the CDN timed out (about 100 seconds on most Cloudflare plans). Time the request directly on the server:

curl -o /dev/null -s -w '%{http_code} %{time_total}s\n' --resolve example.com:443:127.0.0.1 https://example.com/slow-page

Find out why the request is slow

  • PHP slow log: in the FPM pool set request_slowlog_timeout = 5s and slowlog = /var/log/php-fpm-slow.log. It records a stack trace of slow requests.
  • Database: enable the MySQL slow query log, or run SHOW FULL PROCESSLIST; while the page loads to catch long queries or lock waits.
  • External calls: payment gateways, APIs or license checks without timeouts can hang a request. Set short HTTP timeouts in the code.
  • Worker exhaustion: if all PHP-FPM or app workers are busy, new requests wait in a queue until Nginx gives up. Check the FPM status page for a non-zero listen queue.
  • Server overload: high CPU iowait or swapping makes everything slow (top, vmstat 1).

Align the timeouts

When a request legitimately needs longer (an admin export, a report), every layer must allow it. Keep the outer layers slightly longer than the inner ones:

LayerSettingDefault
Nginx → PHP-FPMfastcgi_read_timeout60s
Nginx → app serverproxy_read_timeout60s
PHP-FPM poolrequest_terminate_timeout0 (off)
PHPmax_execution_time30s
Gunicorn--timeout30s

Example for one admin path only, so normal pages keep tight limits:

location ^~ /admin/export {
    fastcgi_read_timeout 300s;
    include snippets/fastcgi-php.conf;
    fastcgi_pass unix:/run/php/php8.3-fpm.sock;
}

Reload Nginx after editing: nginx -t && systemctl reload nginx.

Move long work out of the request

Anything that takes minutes belongs in a background job (queue worker, cron, CLI command) that the page starts and then polls for status. This avoids timeouts at the CDN and the browser altogether.

Check the fix

  • The slow request now completes under the timeouts, measured with curl.
  • The Nginx error log has no new upstream timed out lines.

Troubleshooting

  • 504 on every page suddenly: the backend is hung or overloaded: database locked, disk full, PHP-FPM workers all stuck. Restart cautiously and read the logs.
  • Raised timeouts, still 504 after 100 s: Cloudflare or a load balancer has its own limit.
  • 504 only for uploads: slow client uploads; check client_body_timeout and upload size limits.

504 Gateway Timeout FAQ

Should I just set all timeouts to 10 minutes?

No. Long timeouts let stuck requests pile up and exhaust workers. Raise them only where needed.

Can a 504 be caused by DNS?

Rarely: if Nginx proxies to a hostname that resolves slowly or wrongly. Use IPs or a reliable resolver for upstreams.

Does this apply to cPanel hosting?

The causes are the same, but server timeouts are managed by the host. Optimise the script or ask support.

Next steps

Was this guide helpful?

Still stuck?

Ask MdmHost AI for a quick answer, or open a ticket and our team will take a look. We are here 24/7.