Build your WordPress website with Elementor.Discover Elementor Affiliate link
Français

Site appearance

Failures and errors · Beginner to intermediate

WordPress 504 error: identify the timeout without blindly retrying

Diagnose a WordPress 504 error: gateway, PHP, or external API, using three paths without a new plugin or repeating a sensitive operation.

Source published: · Source updated: · Editorial policy

Read the French edition

Understand what a 504 indicates and what it does not prove

You open a page or start an operation in WordPress, the wait continues, and a “504 Gateway Timeout” page appears. The goal is not merely to make this message disappear: you need a normal response and to establish what happened to the original operation.

A gateway, also called a proxy, receives a request and forwards it to another server. HTTP status 504 means it did not receive the expected response from that upstream server in time. The upstream server may itself be waiting for PHP, a database, or an external service. The number alone therefore does not identify a responsible plugin.

This guide mainly covers self-hosted WordPress with administrator access and authorized access to the hosting panel or its support. It does not require any new plugin. A visitor should record the message and contact the site; they cannot correct server timeouts.

Record the context before touching configuration

Note the affected address, action performed, time with time zone, and approximate wait before the error. Keep a sanitized screenshot of the message and any request ID. State whether the issue follows an update, migration, or traffic increase. These clues let you correlate your test with server logs.

If the dashboard remains accessible, open Tools, Site Health, then Info. Record the WordPress and PHP versions, web server, and affected components. This screen describes the installation; it does not let you change server settings directly. If it does not open, ask the host for this information without repeatedly loading it.

To establish the scope, visit an ordinary public page and, if authorized, an administrative screen without starting an action. A cached page may work while PHP is no longer responding correctly. Conversely, a failure limited to an import does not mean the entire site is unavailable.

If browser developer tools were already open, view Network and select the recorded request: note its status and duration without resending it. This screen may not reconstruct an exchange that happened before it was opened. An application message mentioning 504 may describe a secondary call rather than the whole page. Do not share a network log containing secrets.

Before retrying, check whether the operation already produced a result

After a payment, import, or send operation, do not reload the form or click its button again. An error received by the browser guarantees neither cancellation nor absence of a result. Depending on the application and configuration, processing may continue, stop, or already have saved some data.

Separately open the tracking screen supplied by the component without rerunning its command. For an import, look for its history, task ID, and items actually created. For a WooCommerce store, open WooCommerce, then Orders with an authorized account; inspect the order, its notes, and the payment reference at the provider. This commercial tracking belongs to WooCommerce, not WordPress core.

If the information conflicts, ask support to reconcile the references before deciding to resume. The absence of an email does not prove a payment failed. Do not artificially mark an order paid or issue a refund simply to resolve display uncertainty.

Choose between the three approaches

Use the gateway approach when several pages are affected, a proxy is present, or the problem began after a hosting change. It locates the failure before any WordPress change.

Choose the PHP and components approach when a specific action is slow, resources are saturated, or logs point to local processing. Prepare a controlled reproduction on a copy.

Use the external API approach if a feature waits for a remote service: shipping, translation, payment, or synchronization, for example. Several layers may be involved. Move between approaches according to collected evidence without applying every correction at once.

Approach 1: locate the gateway that stopped waiting

Required access: a browser and, for logs, an authorized hosting panel. This path records the first response to time out without disabling protection. Verify the selected domain in the panel and any official service incident page. A name or logo displayed on the error remains a clue to correlate with logs.

Fictional example: a Document request receives 504 after about 60 seconds, with most time in Waiting for server response. That describes the browser observation; the service named in a header does not prove where the time was consumed. The expected result is a usable record of the request, its duration, and visible relays, not a definitive attribution from the stopwatch alone.

This inspection changes no configuration and requires no rollback. If the error follows a commercial action, use the already captured request instead of replaying it. A direct origin check must preserve the correct domain, certificate, and restrictions, with the administrator.

  1. Open developer tools, then Network. For a new test, choose only a public page view with no business effect.
  2. Reload the page once and select its main Document request. Verify the final URL and status. If the document returns 200 but an action displays a 504, instead inspect the already recorded Fetch/XHR call corresponding to that action; do not resubmit the form to recreate it.
  3. Record the displayed duration, then open Timing to distinguish connecting from waiting for the response. Note the observed label without turning it into a PHP diagnosis.
  4. In Response Headers, record the announced service and an available request ID, such as Ray ID. Do not copy Cookie or Authorization.
  5. Compare a control page. Correlate both results and the time with proxy and origin logs before choosing a timeout.

curl option: measure the first response without following redirects

This optional variant requires curl installed on your computer. Replace the URL with a public, read-only page and choose the line for your operating system. -q must remain first to ignore personal curl configuration; omitting -L retains the first response without following a redirect. Headers and final duration complement the browser check.

The 90-second maximum limits this collection; it does not change the server timeout. If curl reaches its own limit with code 000, that is not an HTTP 504 response. Keep its error message and do not conclude that remote processing stopped. curl may also follow a different path from a browser with a session or JavaScript validation.

Expected result: actual status, total duration, and any identifiers for this read. No site file is changed and no rollback is needed. Headers may contain Set-Cookie: keep them private and add no session secret. Do not replace the domain with an IP address to bypass a protected origin.

# macOS ou Linux : une seule lecture GET
curl -q -sS --connect-timeout 10 --max-time 90 -D - -o /dev/null -w '\ncode=%{http_code} duree=%{time_total}s\n' "https://www.example.com/"
# Windows PowerShell : utiliser cette ligne à la place
curl.exe -q -sS --connect-timeout 10 --max-time 90 -D - -o NUL -w '\ncode=%{http_code} duree=%{time_total}s\n' "https://www.example.com/"

Correlate logs for one identifiable test

In the panel, look for access and error logs for the affected domain; their location depends on the plan. If those screens are unavailable, ask support for entries matching the recorded time. State the time zone, requested path, and available ID without sending cookies or login credentials.

Have connection waiting time to upstream distinguished from waiting for a response that has already started. Also ask whether the origin recorded the request and what duration it observed. The aim is to reconstruct this test’s path, not infer a cause from an unrelated old line.

A 504 at the entry point followed by an operation eventually completed at the origin tells a different story from a stopped process. Preserve that distinction in the diagnosis. No entry in a log proves nothing until its scope, retention period, and activation are confirmed.

Approach 2: examine PHP and the resources actually used

PHP performs much of WordPress’s work. On many hosts, PHP-FPM distributes requests across worker processes. In domain statistics, inspect reached limits and high-usage periods. Ask support whether requests are waiting because no worker is available or whether one process is consuming abnormal resources.

A process limit is not an invitation to double its value. Each process also consumes memory; an excessive setting can worsen the failure. Have changes sized from plan resources and measurements. Ask which domain or group of sites would be affected.

If slowness follows a plugin change, record its name, version, and affected action. Timing is a starting point, not proof. If several heavy processes overlap, ask which can be rescheduled normally after checking their state, rather than killing tasks at random.

Do not confuse PHP time with gateway time

The PHP setting max_execution_time and the proxy timeout measure different things. On systems other than Windows, PHP execution time does not necessarily include time waiting for certain external operations, including database queries. On Windows, it includes real elapsed time. A number shown in PHP therefore does not describe the browser’s entire wait.

PHP-FPM has its own settings as well. request_terminate_timeout can stop a process after an interval; request_slowlog_timeout records the execution stack of a slow request. Their names may sound like immediate fixes, but their purposes differ. Have the hosting administrator use the slow log temporarily, with private storage and a limited collection period.

The useful result is an identified process or wait. Without that, increasing the permitted time may merely keep resources occupied longer. Do not look for a universal value to copy into every file.

Isolate a component without breaking production

Required access: administration of a separate copy, a file/database backup, and a restoration method independent of the dashboard. Check that the copy uses its own database and disable email, payments, and external integrations. The desired result is a reproducible disappearance of the timeout on the same case after isolating a specific component, without extrapolating to all its functions.

If slowness does not change, restore the recorded state before proceeding. Reactivating a component does not restore data the test may have changed; handle those effects separately. Without a reliable copy for an essential feature, choose private analysis or a prepared maintenance window, without globally deactivating production components.

  1. On the copy, open Plugins, then Installed Plugins and record the suspected component’s state and version.
  2. If its role permits this test, click Deactivate for this component alone. Do not rename the entire plugins directory.
  3. Reproduce a read-only case or a small comparable non-sensitive case. Record duration, status, and saved result.
  4. Reactivate the component before testing another. If the symptom changes, have the cause confirmed and verify its correction on the same copy.

Collect a WordPress error without making it public

Required access: files for the correct installation and a private log outside every web root, already present and writable by PHP. Prefer the copy. Replace the example path below with that confirmed path; wp-content/debug.log is not assumed to be private.

Expected result: a new timestamped error matching the test. An empty log rules out neither waiting nor termination before WordPress. If no file appears, check the path with the host rather than widening permissions. To undo a faulty change, restore only the wp-config.php copy without restoring the database.

  1. Download wp-config.php to a private folder, then open the original in a text editor. Locate existing definitions of the three constants.
  2. Change them according to the example without duplicates, before the stop-editing comment and before wp-settings.php loads. Do not add a second PHP opening tag.
  3. Perform a single planned page view or test action. Read new log lines and correlate their times.
  4. Correct the identified component on a copy and compare the same case. Keep only the necessary excerpts privately.
  5. Return the constants and display_errors to their initial state after collection; do not leave debugging active by default.
define( 'WP_DEBUG', true );
define( 'WP_DEBUG_LOG', '/CHEMIN/PRIVE/EXISTANT/wp-504.log' );
define( 'WP_DEBUG_DISPLAY', false );
@ini_set( 'display_errors', 0 );

Approach 3: check an external API without repeating its action

An API is an interface through which WordPress or a plugin communicates with another service. If only one integrated function fails, check that service’s official status and the history available in the component. Record the service name, time, operation reference, and message while hiding keys and personal data.

Distinguish an actual HTTP 504 response received from the API from a local error reporting that WordPress did not receive a response in time. The WordPress HTTP API has its own timeout and may return an error without a usable HTTP response. A plugin may also use another network client; its setting is not necessarily WordPress’s setting.

Ask the publisher to correlate the remote reference with local logs and explain the intended recovery mechanism. If the service accepted the action, continue tracking it rather than creating a second one. If no reliable state is available, keep the operation marked unconfirmed.

Do not remove certificate verification or allow every outgoing connection to hide the symptom. A change must target the demonstrated service and cause.

Optional on a copy: attribute waiting time with Query Monitor

Query Monitor, a free plugin by John Blackbourn, is optional: use it on an accessible copy with an administrator account after checking current prerequisites. On multisite, its data is restricted to the super administrator by default. It observes calls and queries for the current page load, not the history of a previous payment. It reverses no effects and adds diagnostic collection of its own; do not replay a sensitive action to populate its panels.

Expected result: a call, its duration, its outcome, and the calling component are correlated with the case being examined. If PHP is interrupted before producing data, the tool may display nothing: return to private logs. An absent call in this panel does not prove that a component using another network client sent nothing.

  1. On the copy, open Plugins > Add New Plugin, search for Query Monitor and verify John Blackbourn as author, then install and activate only if necessary.
  2. Open a control page that completes. In the admin bar, open the Query Monitor menu or its diagnostic figures.
  3. Inspect HTTP API Calls: record the sanitized service address, duration, code or error, and responsible component.
  4. In Queries, then Queries by Component, compare SQL time and component. With Query Monitor 4, Timeline also helps place calls and queries within the page load.
  5. Test the correction on this same page view. To undo the diagnostic addition, deactivate and remove the temporary tool if no longer useful; other test changes remain separate.

For long imports, prefer the tool’s intended resume mechanism

When the problem concerns an import, consult its documentation and tracking screen before splitting it. Check whether the tool retains progress, recognizes already processed items, and can resume a batch. A smaller file does not prevent duplicates if every retry recreates the same content.

On the secured copy, select a limited, identifiable batch. Keep the source file and expected item IDs. After the authorized test, check creations, updates, and rejections. If processing still exceeds the timeout, stop new tests and send these results to the tool’s support.

Background processing or hosting tools may be suitable when expressly supported. They do not guarantee the absence of limits and still require monitoring. Do not turn a complete import command into a repeated task to bypass the error page.

Change a timeout only after identifying its scope

This optional branch is for a server administrator; it does not replace fixing stalled processing. A fictional, bounded example: logs confirm that legitimate processing finishes after 75 seconds without sending headers before completion, resources allow it, and the FastCGI wait for this site alone expires at 60 seconds. A 90-second target can then be tried if other relays do not cut off earlier.

Required access: SSH and permission to change the Nginx configuration actually loaded for this domain. The reload example assumes Linux with systemd and a service named nginx; elsewhere, use the command confirmed by your administrator. fastcgi_read_timeout controls the wait between FastCGI reads, not a universal total duration. An HTTP proxy uses proxy_read_timeout, and Apache has its own directives; do not add this setting to WordPress or .htaccess.

Expected result: the intended process finishes within the justified window without worsening resource usage. If waiting persists, return only the directive to its initial value; you can restore the saved file if nobody has changed it in the meantime. Validate with nginx -t, then reload after success. On a managed plan, this branch belongs to the provider: send the value, measured reason, and requested rollback.

  1. Using the private read sudo nginx -T, identify the file and PHP block for this domain. If the panel generates this configuration, use its mechanism instead of editing the generated file.
  2. Keep the file outside the Web under an unused name. In the example, replace the site path and backup name.
  3. In the existing PHP block, change only the confirmed directive from 60s to fastcgi_read_timeout 90s;. Keep the old value in your record.
  4. Run the syntax test. If it fails, restore or correct the configuration and do not reload. Run commands one at a time, reloading only after success.
  5. Check the intended page view and resources. If the result is no better, apply the described rollback before trying another setting.
sudo cp -p /etc/nginx/sites-available/example.com /root/example.com.nginx-avant-504
sudo nano /etc/nginx/sites-available/example.com
sudo nginx -t
# Uniquement après réussite du test :
sudo systemctl reload nginx

Adapt the procedure for WordPress.com and multisite

On WordPress.com, start with support and the features actually accessible in your account. Files and server settings available on a self-hosted installation are not necessarily editable on this platform. Send the affected page and observations; do not install a plugin solely to try changing a hosting-imposed timeout.

In a multisite network, compare the affected subsite with another without starting a commercial operation. Some plugins are managed at network level, and several sites share resources. Involve the network administrator before any deactivation or shared change. A correction must preserve other subsites, not only the address used for diagnosis.

Check the result and restore protections

After the targeted correction, first open the affected ordinary pages. Then, with authorization, test a comparable, non-sensitive operation. Record its duration, saved result, and any new errors. An accessible homepage is not enough to validate an import that was failing in the dashboard.

For a payment whose state remains uncertain, first finish reconciling the original operation. Do not make a new real purchase to verify that the message is gone. On a copy, use only the officially supported test mode and check for absence of real effects.

Restore necessary components, turn off temporary debugging, and keep a record of the retained change. If the correction works only while a protection is disabled, diagnosis is not finished. The goal remains normal functionality with the usual protections.

Send a useful case file and prevent recurrence

If you need to escalate, gather the domain, versions, time and time zone, affected path, wait duration, and operation references. Add sanitized excerpts and attempted changes with their results. State what remains unknown, particularly the state of an import or payment.

Ask which layer produced the 504, whether processing is still active, and which action can be resumed without duplicates. If the host and publisher are both involved, send the same references to both contacts to avoid two diagnoses of different tests.

Finally, keep a record of limits and scheduled windows for heavy processing. Test important changes on a protected copy and regularly verify backups. A controlled 504 incident is resolved through an identified cause and a checked result, not successive retries.

Distinguish the durations within one incident

For the maintainer, three durations can explain very different situations: connecting to the upstream server, waiting for its first headers, and receiving its entire response. With Nginx, the logging variables upstream_connect_time, upstream_header_time, and upstream_response_time distinguish these stages when recorded. Their availability and interpretation depend on the actual path used; the server owner chooses the private log format.

Fictional example: a fast connection followed by sixty seconds without initial headers calls for different checks from a connection that is impossible throughout that time. In the first case, correlate PHP processing and external calls; in the second, first inspect upstream availability and connectivity. If several upstreams were attempted, do not reduce their different values to a single duration without explanation.

Have these measurements correlated with the same test’s identifier. A gateway access line and a PHP error from another minute do not form a chain of evidence. This collection uses server tools; installing a WordPress plugin cannot retroactively measure a connection that failed before WordPress loaded.

Sources and references

Use these references to check the features, requirements and limitations described. Reading documentation is not a practical test.

View 24 references

English translation of the reviewed French edition. Code examples retain their original identifiers, comments and output strings for reproducibility. Linked exercise files and original screenshots may contain French. No new practical tests or price checks are implied by translation.

Continue reading in English