Fixing 504 Gateway Time-out: How to Resolve Nginx Upstream Timeouts

intermediate🌐 Networking2026-06-15| Linux (Ubuntu/CentOS/Debian), Nginx 1.18+, PHP-FPM, Python/Gunicorn, Node.js

Error Message

504 Gateway Time-out
#nginx#gateway-timeout#networking#proxy#php-fpm#devops

The Problem

Few things are as frustrating as staring at a blank screen while your browser spits back a 504 Gateway Time-out error. This happens when Nginx acts as a middleman (a proxy) and successfully forwards a request to your backend—like PHP-FPM, Gunicorn, or Node.js—but that backend takes too long to answer. Technically, Nginx loses patience and shuts down the connection because the response didn't arrive within the allowed window.

Identify the Root Cause

Before you start blindly tweaking config files, check your Nginx error logs to confirm which service is stalling. Run this command to watch the logs in real-time:

sudo tail -f /var/log/nginx/error.log

Keep an eye out for a line that looks like this:

[error] 12345#0: *678 upstream timed out (110: Connection timed out) while reading response header from upstream, client: 1.2.3.4, server: example.com, request: "GET /api/reports HTTP/1.1", upstream: "http://127.0.0.1:8000/api/reports"

If you see "upstream timed out," it confirms that the application running on port 8000 is the bottleneck. By default, Nginx waits 60 seconds for a response; if your report or API call takes 61 seconds, it triggers a 504.

Solution 1: Increase Nginx Proxy Timeouts

If you use Nginx as a reverse proxy for Node.js, Python, or Go, you need to extend the wait times in your server or location block. Most users find that 300 seconds (5 minutes) is plenty for heavy processing.

Open your site configuration (usually /etc/nginx/sites-available/default) and update these lines:

location / {
    proxy_pass http://your_backend;
    proxy_connect_timeout 300s;
    proxy_send_timeout 300s;
    proxy_read_timeout 300s;
    send_timeout 300s;
}
- **proxy_connect_timeout:** How long Nginx waits to establish a handshake with the backend.
- **proxy_read_timeout:** The most common culprit. This is how long Nginx waits for the backend to send back data after the connection is open.
- **proxy_send_timeout:** The time Nginx waits to finish sending your request to the backend.

Solution 2: Fix 504 Errors for PHP-FPM

For WordPress or Laravel sites, simply changing Nginx isn't enough. PHP-FPM has its own internal timers that will kill a script even if Nginx is still waiting.

1. Update Nginx FastCGI Config

location ~ \.php$ {
    include snippets/fastcgi-php.conf;
    fastcgi_pass unix:/var/run/php/php8.2-fpm.sock;
    fastcgi_read_timeout 300s;
}

2. Update PHP-FPM Pool Settings

Edit your pool configuration (e.g., /etc/php/8.2/fpm/pool.d/www.conf) and set request_terminate_timeout to match your Nginx settings:

request_terminate_timeout = 300

3. Update php.ini

Finally, ensure your PHP execution limit allows for the extra time:

max_execution_time = 300

Solution 3: Fix 504 Errors for Python (Gunicorn/Uvicorn)

Gunicorn is notoriously strict, with a default timeout of only 30 seconds. If a data export takes 35 seconds, Gunicorn will kill the worker process, leading Nginx to report a 504 error because the connection vanished.

Launch Gunicorn with a higher timeout flag:

gunicorn --timeout 300 myapp.wsgi:application

Verification Steps

Once you have adjusted the settings, verify that your Nginx syntax is still valid:

sudo nginx -t

If the test is successful, reload the services to apply the new limits:

sudo systemctl reload nginx
sudo systemctl restart php8.2-fpm  # Only if you are using PHP

Test the request again. If you still hit a 504 after exactly 300 seconds, the timeout is likely happening further upstream at a Cloudflare or AWS Load Balancer level.

Prevention and Optimization

Raising timeouts stops the error page from appearing, but it doesn't fix a slow backend. Long-running requests hog worker processes and can eventually crash your server under heavy traffic.

- **Optimize Database Queries:** A missing index on a table with 500,000 rows is a classic cause of 504 errors.
- **Offload to Background Jobs:** If a task takes longer than 10 seconds (like sending 50 emails or generating a PDF), don't make the user wait. Use a queue like Celery or Redis and return a "Processing" message immediately.
- **Inspect the Network:** If Nginx and the backend live on different servers, latency can eat into your timeout window. I often use this [Subnet Calculator](https://toolcraft.app/en/tools/developer/ip-subnet-calculator) when mapping out VPCs to ensure internal routing is efficient and doesn't introduce unnecessary hops.

Summary

A 504 Gateway Time-out is essentially Nginx telling you that your backend is struggling. To fix it permanently, you must align timeout values across your entire stack: the browser, the load balancer, Nginx, and finally the application server itself. If any part of this chain times out too early, the whole request fails.

Related Error Notes