Do these 3 things before closing this tab:
1Clear out junk files and repair common Windows errors2Scan for outdated or missing drivers - takes under a minute3Repair Windows errors before they cause bigger problemsA 504 Gateway Timeout means Nginx (or another gateway) waited too long for an upstream response. In a WordPress stack, that upstream can be PHP-FPM, a second web server, a database-dependent application request, a load balancer, or an external API. Find the exact request and the layer that stopped responding before changing a timeout. Then fix the slow or unavailable component and only increase the matching Nginx timer when the operation is legitimate and consistently needs more time.
Antihost offers managed WordPress hosting with free migration, one-click staging and a 14-day free trial.
What a 504 means on a WordPress server
HTTP 504 is the GATEWAY_TIMEOUT status. It describes a failure at a gateway boundary, not a diagnosis of Nginx itself. Nginx may be waiting for PHP-FPM through FastCGI, for another HTTP service through proxy_pass, or for a load-balanced upstream. WordPress can also spend the request inside a plugin, theme, database query, image operation, cron task, import, backup, or remote API call.
As an Amazon Associate I earn from qualifying purchases.
Recommended Free Tools
The browser may show the same 504 page for very different failures. A request that always stops after about 60 seconds is different from one that fails immediately because a PHP-FPM socket is unavailable, and both are different from a request killed by PHP before Nginx reaches its own limit. Treat the displayed error as a starting symptom.
Start with evidence, not a larger timeout
1. Capture the failing request
Write down the full URL, HTTP method, exact UTC or server-local timestamp, and the operation that failed. Record whether it was a public page, wp-admin screen, REST endpoint, AJAX action, scheduled cron request, publishing action, import, export, backup, or media transformation. Note whether every visitor is affected or only one account or operation. A reproducible admin-only failure points toward application work; a site-wide failure may involve the upstream service, worker pool, or infrastructure.
2. Read the Nginx error log at that time
Search the error log for upstream timed out, the upstream address or FastCGI socket, and wording that says whether Nginx was waiting for response headers or later response data. The line’s timestamp must match the captured request. A timeout while reading response headers usually means the application had not produced headers; a timeout while reading later data can indicate that a response began and then stopped.
Access logs become much more useful when they include request duration and upstream response duration. NGINX’s logging documentation describes timing fields that let you compare the total request time with time spent waiting on the upstream. If the upstream duration is nearly the whole request, investigate PHP-FPM or the proxied service. If upstream time is short but the total is long, inspect another layer such as buffering, a load balancer, or the client connection.
3. Preserve a working comparison
Run a fast request from the same host or network, such as the home page and a lightweight health endpoint, then compare it with the failing URL. If only one endpoint times out, do not apply a server-wide change. Save the exact log excerpts before editing configuration so you can tell whether a change improved the request or merely moved the failure to another layer.
Map the request to the correct upstream
Open the active server block and follow the location that handles the failing URL. WordPress Nginx guidance commonly sends PHP files to PHP-FPM with fastcgi_pass. A reverse-proxy arrangement sends requests to another HTTP service with proxy_pass. The directive you change must match that path.
| Request path | What Nginx is waiting for | Relevant setting | Typical evidence |
|---|---|---|---|
| Reverse proxy | An HTTP response from the server named in proxy_pass |
proxy_read_timeout |
Error log names a proxied upstream address |
| PHP through FastCGI | Response data from PHP-FPM named by fastcgi_pass |
fastcgi_read_timeout |
Error log names a Unix socket or FastCGI host |
| PHP-FPM process management | A free worker and a process allowed to continue | request_terminate_timeout and pool settings |
PHP-FPM log shows termination, a full pool, or worker failures |
| PHP runtime | Script execution within PHP’s limits | max_execution_time and platform limits |
PHP log or application log shows a script limit or fatal error |
| Database or external service | Query or remote API completion | Application and service-specific limits | WordPress debug log shows a slow query, blocked call, or API error |
| Load balancer or managed platform | An upstream response within the platform’s limit | Provider-specific setting | Failure occurs at a precise platform interval and server access is restricted |
The table separates responsibility; it does not assign a universal cause. No authoritative industry study establishes a fixed percentage of WordPress 504 errors caused by Nginx, PHP-FPM, plugins, databases, or hosting.
Understand Nginx timeout behavior
proxy_read_timeout is for proxy_pass
Current NGINX module documentation lists a 60-second default for proxy_read_timeout. It is an idle-read timer: Nginx closes the connection when the proxied server transmits nothing during the interval. It is not a maximum stopwatch for the entire response.
The Tool Desk
Outbyte Driver Updater FREEScan for outdated or missing drivers - takes under a minuteDriver Scan →Outbyte PC Repair FREERepair Windows errors before they cause bigger problemsFix Now →Rank #2
NGINX states that the timeout is set only between two successive read operations, not for transmission of the whole response. A streaming upstream that periodically sends data can therefore remain connected longer than 60 seconds, while an upstream that sends nothing can time out even when the eventual work would have completed.
fastcgi_read_timeout is for PHP-FPM
When the location uses fastcgi_pass, inspect fastcgi_read_timeout in that active location or inherited configuration. Do not change proxy_read_timeout and expect a FastCGI request to change; the directives apply to different upstream protocols.
Why a 60-second failure is not automatically an Nginx fault
A request can be killed by PHP-FPM’s request_terminate_timeout, PHP’s max_execution_time, a load balancer, or a hosting platform before Nginx reaches its read timer. Conversely, Nginx can stop waiting while PHP-FPM continues consuming a worker. Measure the interval in logs and compare it with every layer’s configured limit.
Check PHP-FPM and PHP limits before editing Nginx
Inspect the PHP-FPM pool serving the site. Compare its request_terminate_timeout with the Nginx FastCGI timer, and check whether the pool has enough available workers. A saturated pool can make otherwise healthy requests wait for a worker. A process that PHP-FPM terminates cannot be kept alive by giving Nginx a longer read timeout.
Free tools Windows power users keep installed
One-click scans. No signup required.
Check PHP’s max_execution_time and any platform-level execution or request limit. The shortest applicable inner limit wins. Record the configured values and their scope: pool, virtual host, site, container, or entire server. Avoid assuming that a value shown in a command-line PHP configuration is the value used by the web-serving PHP-FPM pool.
Look in the PHP-FPM log for terminated requests, children reaching the process limit, slow requests, out-of-memory events, and failure to connect to the database. A 504 accompanied by a PHP fatal error or worker restart requires an application or resource fix, not a larger Nginx timer.
Rank #3
Enable WordPress logging safely
For a short diagnostic window, add these constants to wp-config.php before the line that says WordPress should stop editing:
define( 'WP_DEBUG', true );
define( 'WP_DEBUG_DISPLAY', false );
define( 'WP_DEBUG_LOG', true );
WordPress documents that this enables debugging, keeps errors off the public page, and writes them to wp-content/debug.log. Reproduce the exact failing operation, then inspect the entries at the matching timestamp. Protect the log from public access, because it can contain paths, queries, request data, or secrets. Remove the temporary settings or restrict them appropriately after diagnosis.
A blank debug log does not prove that the request was healthy. The request may have died before WordPress loaded, PHP logging may be configured elsewhere, or the failure may be in Nginx, PHP-FPM, a load balancer, or an external service. Correlate WordPress, PHP-FPM, and Nginx timestamps.
Isolate WordPress application causes
Plugin and theme code
If one admin screen, AJAX action, REST route, publishing action, or front-end URL fails, reproduce only that operation while watching all three logs. Temporarily disable plugins and test with a default theme, preferably during a maintenance window or with a method that does not disrupt visitors. Re-enable components one at a time until the timeout returns. A component that performs a remote API call, rebuilds a large index, processes media, or triggers a recursive loopback can make a single request exceed the gateway’s idle period.
Database work
Look for a query that scans a large table, waits on a lock, performs an unbounded report, or runs repeatedly inside a loop. Check database error and slow-query logs where available. Reduce the data set, add an appropriate index after verifying the query plan, paginate administrative work, or move maintenance into a background job. Increasing the gateway limit while a query remains blocked consumes a PHP-FPM worker for longer and can worsen the outage.
Remote APIs and loopbacks
External HTTP calls can stall when a remote service is unavailable, DNS is slow, TLS negotiation fails, or the application has no sensible client timeout. WordPress loopback requests can also fail when authentication, firewall rules, or a plugin causes recursion. Identify the remote hostname and call duration in application logs. Set a bounded client timeout and handle failure explicitly rather than allowing the web request to wait indefinitely.
Memory and large operations
Imports, backups, image generation, and publishing workflows may exceed PHP memory or worker capacity. Check for memory exhaustion and partial files. Split large jobs into batches or queue them for background processing. A request that reliably needs several minutes may be the wrong work unit for a synchronous browser request even if every timeout is increased.
Choose a fix based on evidence
| Remediation | Use it when | Scope | Risk |
|---|---|---|---|
| Fix plugin, theme, query, or API behavior | Logs identify slow or blocked application work | Specific component or operation | Requires code or workflow changes, but removes the underlying delay |
Increase fastcgi_read_timeout |
A legitimate PHP request consistently needs more time and PHP-FPM can safely run it | Prefer one location or endpoint | Longer waits tie up PHP-FPM workers |
Increase proxy_read_timeout |
The failing path uses proxy_pass and the upstream is healthy but legitimately quiet |
Prefer one proxied location | Can hide an unavailable upstream and retain connections |
| Adjust PHP-FPM or PHP limits | An inner limit terminates the request before Nginx | Pool, site, or PHP runtime | Higher limits increase CPU, memory, and worker consumption |
| Ask the host to change platform limits | Managed hosting prevents access to Nginx, PHP-FPM, or load-balancer settings | Provider-controlled | Requires a support escalation and may be subject to plan limits |
The strongest evidence is a repeatable duration plus a matching log line. Do not apply a very large global timeout to every location merely because one import or report is slow.
Raise the matching Nginx timer carefully
For a reverse-proxied endpoint
Inside the specific location that contains proxy_pass, use a modest value supported by the upstream’s expected work. For example:
location /api/long-job/ {
proxy_pass http://application_backend;
proxy_read_timeout 120s;
}
This changes the maximum idle gap between reads for that location. It does not repair an upstream that never responds, and it does not change PHP-FPM limits.
Windows Errors? Fix Them Before They Spread
Repair common Windows errors and clear accumulated junk for a smoother, more stable PC - no reinstall needed.Free scan · no reinstallOutdated Drivers Are Slowing You Down
One free scan finds every outdated or missing driver and matches the right update for your exact hardware.Free scan · exact hardware matchFor PHP-FPM through FastCGI
In the PHP location that contains fastcgi_pass, set the corresponding read timer:
location ~ .php$ {
include fastcgi_params;
fastcgi_pass unix:/run/php/php-fpm.sock;
fastcgi_read_timeout 120s;
}
The socket path and included parameter file must match your installation. Do not paste this block over a working WordPress server block without checking its existing security and routing rules. Limit the longer timeout to the operation that needs it whenever possible.
Best Value
Align the inner limits
If you intentionally allow 120 seconds at Nginx, verify that PHP-FPM’s termination limit, PHP execution limit, load-balancer limit, and application client timeouts are compatible. There is no benefit in setting Nginx to five minutes when PHP-FPM terminates the process at one minute. Conversely, increasing PHP-FPM without allowing the gateway to wait can still produce a 504.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Validate, reload, and reproduce
- Back up the active Nginx configuration and note which file and location you changed.
- Run
nginx -t. Do not reload if syntax validation fails; correct the reported file and line first. - Reload Nginx using your system’s service manager, for example
systemctl reload nginx, after a successful test. - Confirm the active configuration rather than assuming an unused file was loaded. Check included files and the server block selected for the request.
- Repeat the same URL, method, payload, account, and operation that originally failed.
- Compare Nginx timing fields, PHP-FPM entries, WordPress debug entries, and the response status before and after the change.
If the 504 still appears at a precise interval, identify which layer owns that interval. Repeatedly changing unrelated directives creates a longer wait without changing the failing component.
Use a decision tree for common symptoms
- Only one URL or button fails: isolate its plugin, theme callback, query, remote API, or payload before changing global settings.
- All PHP pages fail and logs name the FastCGI socket: check PHP-FPM availability, socket permissions, worker health, and pool saturation.
- Only proxied routes fail: inspect the service behind
proxy_pass, its health, and its own access and error logs. - Failure occurs at exactly 60 seconds on a proxied path: compare that interval with the documented default of
proxy_read_timeoutand confirm that the upstream sends no data during the gap. - PHP logs show termination before the Nginx error: fix the PHP-FPM or PHP limit and the underlying workload; Nginx cannot revive a terminated process.
- The request succeeds from the server but fails through the public domain: inspect the load balancer, CDN, firewall, or another gateway between the client and Nginx.
- Only managed-hosting sites are affected and configuration is inaccessible: provide the host with a timestamp, full URL, request type, Nginx error line, PHP-FPM excerpt, and reproducibility details.
When to involve your hosting provider
Managed WordPress plans may hide global Nginx, PHP-FPM, and load-balancer settings. WordPress support guidance recommends contacting the host when you cannot inspect or change those layers. Ask for the timeout owner, the upstream named in the log, the configured limits, and any worker or memory errors.
Send a concise incident package:
- Exact timestamp with timezone and the affected hostname.
- Full URL, HTTP method, and whether the request was front-end, admin, REST, AJAX, cron, import, backup, or publishing traffic.
- Nginx error-log line containing the upstream and timeout wording.
- Related PHP-FPM and WordPress debug-log excerpts with secrets removed.
- Whether the failure affects all users and whether it reproduces at the same interval.
- Any recent plugin, theme, PHP, database, or configuration change.
Do not send a public debug log or credentials. Ask the provider to confirm the active Nginx, PHP-FPM, and load-balancer limits rather than simply raising every limit.
Prevent recurring 504s
Keep timing-aware logs
Retain request and upstream timing fields long enough to compare incidents. Alert on rising upstream latency, repeated 5xx responses, and a growing number of busy PHP-FPM workers. A monitoring system that checks only the home page can miss a failing admin, REST, or background endpoint; include the critical operations your site actually uses.
Design long work as jobs
Move large imports, backups, reports, media conversions, and maintenance tasks out of a single browser request when possible. Process bounded batches, persist progress, and let the user poll job status. This reduces the time any one PHP-FPM worker remains occupied and avoids relying on gateway timers as a job queue.
Review changes after upgrades
Record PHP, WordPress, plugin, theme, database, and Nginx changes. A new component may add a remote call or query that turns a previously fast request into a timeout. Reproduce in a staging environment with comparable data and inspect logs before changing production limits.
Bottom line
Fix the layer that the logs identify. Use proxy_read_timeout only for a proxy_pass path and fastcgi_read_timeout only for a FastCGI/PHP-FPM path. Remember that both are idle-read timers, not guarantees that an application will finish. A modest, location-specific increase is reasonable for a healthy operation with a documented runtime; a huge global value merely lets slow queries, blocked workers, broken plugins, or unavailable services consume resources longer.
Quick Recap
Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.




