PQ
PQ.Hosting

Currency

Nginx 504 Gateway Timeout: Causes and How to Fix It

Author
PQ
March 12, 2026
4 min read
34 views

504 appears when Nginx was waiting for a response from the backend — php-fpm, Apache, Node.js — and timed out. Nginx itself is working fine. The problem is either that the backend hung, or that the script runs longer than the configured timeouts allow. Two different scenarios, two different fixes.

First: Find Where the 504 Is Happening

Before changing timeouts — check how often the error occurs and on which URLs:

grep " 504 " /var/log/nginx/access.log | tail -50

More details from the error log:

grep "504" /var/log/nginx/error.log | tail -30

If 504 is on one specific URL — likely a heavy script or a hung process. If it's everywhere — server overload or a crashed php-fpm.

Check Server Resources

If the server is overloaded — increasing timeouts will only delay the error, not fix it.

Free RAM:

free -h

CPU load and top processes:

htop

php-fpm status:

systemctl status php8.1-fpm

If php-fpm is consuming all CPU cores or has crashed — that is the cause of the 504. Fix: optimize scripts, add caching, or upgrade the VPS.

Increase Timeouts for php-fpm (FastCGI)

If a script intentionally runs for a long time — importing a large file, generating a report, processing video — Nginx by default cuts the connection after 60 seconds.

Open the virtual host config or the location block where fastcgi is used:

sudo nano /etc/nginx/sites-available/mysite

Add inside location ~ \.php$:

fastcgi_connect_timeout 300;
fastcgi_send_timeout 300;
fastcgi_read_timeout 300;

The three directives cover different phases: connecting to php-fpm, sending data, and waiting for a response. All three need to be set for long scripts — otherwise 504 may return at a different stage.

Test config and reload:

sudo nginx -t && sudo systemctl reload nginx

Increase Timeouts for Reverse Proxy (Apache, Node.js)

If Nginx proxies requests to another server — use proxy directives. Add inside the server or location block:

proxy_connect_timeout 300;
proxy_send_timeout 300;
proxy_read_timeout 300;
send_timeout 300;

After changes:

sudo nginx -t && sudo systemctl reload nginx

Also Increase the Timeout on the php-fpm Side

Nginx can wait patiently, but if php-fpm terminates the script first — 504 returns. Set the execution timeout in the pool config:

sudo nano /etc/php/8.1/fpm/pool.d/www.conf
request_terminate_timeout = 300

And in php.ini:

sudo nano /etc/php/8.1/fpm/php.ini
max_execution_time = 300

Restart php-fpm:

sudo systemctl restart php8.1-fpm

Find Slow Scripts via slow-log

If 504 occurs for users intermittently and the problematic script is unknown — enable slow-log in php-fpm. It records scripts that took longer than the configured threshold.

Open the pool config:

sudo nano /etc/php/8.1/fpm/pool.d/www.conf

Add:

slowlog = /var/log/php-fpm/www-slow.log
request_slowlog_timeout = 5s

Restart php-fpm:

sudo systemctl restart php8.1-fpm

Watch what accumulates:

tail -f /var/log/php-fpm/www-slow.log

The log contains a stack trace — shows which function or database query is the bottleneck. More precise than guessing from access.log URLs.

Check php-fpm Worker Count

If all workers are busy — new requests queue up and cause 504 even on fast scripts.

Check current php-fpm processes:

ps aux | grep php-fpm | grep -v grep | wc -l

Compare with pm.max_children in the pool config. If the process count equals max_children — all workers are occupied, increase it:

pm.max_children = 20
pm.start_servers = 5
pm.min_spare_servers = 5
pm.max_spare_servers = 10

Quick Reference

Cause of 504 Fix
Script runs longer than Nginx timeout fastcgi_read_timeout 300 in location
Nginx proxying to Apache/Node.js proxy_read_timeout 300 in server/location
php-fpm terminates script too early request_terminate_timeout = 300 in www.conf
All php-fpm workers busy Increase pm.max_children
Server overloaded htop, free -h, optimize or upgrade VPS
Unknown which script is slow Enable slowlog in php-fpm
Find 504 URLs in logs grep " 504 " /var/log/nginx/access.log

Share this article