/ โ† HTTP Error Fixes / 504 Gateway Timeout
In this guide
  1. A 504 is a chain of stopwatches
  2. Working out which timeout fired
  3. Catching the slow step in the act
  4. The fix, step by step
  5. When raising the timeout is the right answer
  6. Patterns that point to the cause
  7. What 504s mean for search engines
  8. Keeping timeouts away
  9. Questions and answers

A 504 is a chain of stopwatches

Between a visitor and your code there are usually several programs, and each one starts its own stopwatch when it hands the request inward. The first stopwatch to run out produces the error. That is why the same slow page can show a 504 on one day, a CDN error on another, and simply load very slowly on a third.

LayerSetting that limits the waitCommon defaultWhat the visitor sees
Cloudflare (proxied)Origin response timeout100 seconds on most plansCloudflare error 524, not 504
Cloud load balancerIdle timeoutOften 60 seconds, but check your provider504 from the load balancer
nginx proxying to an appproxy_read_timeout60 seconds504 from nginx
nginx passing to PHP-FPMfastcgi_read_timeout60 seconds504 from nginx
Apache with mod_proxyProxyTimeout, falling back to Timeout60 seconds504 from Apache
PHP-FPM poolrequest_terminate_timeout0, meaning no limitUsually a 502, because the worker is killed mid-request
PHP itselfmax_execution_time30 seconds for web requestsA 500 or a PHP fatal error

Defaults change between versions and hosts often override them, so treat the table as a guide and check the real values on your server. The pattern matters more than the numbers: if the outer layer's limit is shorter than the inner layer's, the outer one fires first and you get a 504 with nothing useful in your application log.

๐Ÿ’ก PHP's max_execution_time on Linux counts time spent running PHP code, not time spent waiting on the database, an external API or a file download. A script waiting 90 seconds for a slow query will not hit a 30-second PHP limit, but nginx will give up at 60 seconds and return a 504.

Working out which timeout fired

Time the request first. The number of seconds before the error usually identifies the layer straight away.

curl -s -o /dev/null -w "status %{http_code}  total %{time_total}s  first byte %{time_starttransfer}s\n" \
  "https://www.example.co.uk/reports/annual-summary/?year=2025"

Then confirm it in the web server error log. nginx writes a distinctive line for this case:

upstream timed out (110: Connection timed out) while reading response header from upstream,
client: 198.51.100.24, server: www.example.co.uk, request: "GET /reports/annual-summary/?year=2025 HTTP/2.0",
upstream: "fastcgi://unix:/run/php/php8.3-fpm-example.sock"

"While reading response header" means the connection worked and the application was simply too slow. "While connecting to upstream" means nginx could not even open the connection in time, which points at an overloaded or unreachable back end instead.

One URL or all of them?

If one report page, search or export fails, the slowness is in that page's own work. If every page times out at once, something shared is stuck: the database, a full pool of workers, a lock on a table, or a service every page calls, such as a session store. When all PHP-FPM workers are busy on slow requests, even fast pages wait in the queue behind them and time out too, so one slow page can take down the whole site.

Catching the slow step in the act

Once you know the request is too slow, you need to know where the time goes. Three tools answer that without guesswork.

The PHP-FPM slow log

PHP-FPM can write a stack trace of any request that runs longer than a threshold. The trace shows the function it was in at that moment, which usually points straight at a database call, an HTTP request or a loop.

; in the site's PHP-FPM pool file
request_slowlog_timeout = 10s
slowlog = /var/log/php-fpm/example-slow.log

Reload PHP-FPM, trigger the slow page, and read the file. A trace ending in curl_exec() means an outgoing web request; one ending in a database driver function such as mysqli_query() or PDOStatement->execute() means a query.

The database slow query log

-- MySQL or MariaDB, until the next restart
SET GLOBAL slow_query_log = 'ON';
SET GLOBAL long_query_time = 2;
SHOW VARIABLES LIKE 'slow_query_log_file';

Run EXPLAIN on any query that appears. A type of ALL on a large table means every row is scanned, and the usual fix is an index on the columns in the WHERE and ORDER BY clauses. For PostgreSQL, the equivalent setting is log_min_duration_statement.

Application monitoring

An application performance monitoring tool, or a framework debug bar on a staging copy, breaks a request into database, cache, external call and code time. If you have one, it is the fastest way to see the slow step for a specific URL.

The fix, step by step

Step 1

Measure how long the failing request takes

Take a URL the HTTP Error Audit flagged with a 504 and time it with curl -w, printing the status code, total time and time to first byte. Try it several times, and at a quieter hour. Note the exact number of seconds before the error, because a result close to 60 or 100 seconds points to a particular layer, and note whether other pages are slow at the same moment.

Step 2

Identify which timeout fired

Look at who sent the error page and search the web server error log for the request. upstream timed out while reading response header means the application was too slow; while connecting to upstream means it could not be reached. A Cloudflare 524 means the origin missed Cloudflare's limit. List every timeout between the visitor and your code, with its current value, before changing any of them.

Step 3

Record what the slow request is doing

Switch on the PHP-FPM slow log with request_slowlog_timeout set to around ten seconds, and the database slow query log with long_query_time set to a couple of seconds. Trigger the failing page, then read both logs. The stack trace shows whether the time goes on a query, an outgoing HTTP call, file work or a loop, and the query log names the statement involved.

Step 4

Fix slow queries and external calls

Run EXPLAIN on slow queries and add indexes for the columns used to filter and sort, or rewrite queries that load whole tables. Cache results that do not change on every request. For calls to other services, set a short connect and response timeout of a few seconds on the outgoing request, and show a fallback if the service does not answer, so one slow partner cannot hang your page.

Step 5

Move long jobs out of the request

Imports, exports, large reports, bulk emails and image processing should not run while a visitor waits. Put the job on a queue or run it from a scheduled task, return a page straight away saying the work has started, and let the visitor download the result or receive an email when it finishes. The web request then takes a second or two, whatever the size of the job.

Step 6

Line up the timeouts from inside out

Once the work itself is fast, set the timeouts so each inner layer gives up before the layer outside it. For example, the outgoing API call gives up first, then PHP-FPM with request_terminate_timeout, then nginx with fastcgi_read_timeout, then the load balancer or CDN. Raise an outer limit only for the specific admin or export path that genuinely needs it, not site-wide.

Step 7

Retest under realistic load

Request the fixed page several times with curl and confirm a 200 well inside the limits, then re-run the HTTP Error Audit so pages are fetched in quick succession, much as a crawler does. Check the slow logs again afterwards to make sure nothing new appears. Turn the database slow query log threshold back up, or off, if it is producing more output than you need.

When raising the timeout is the right answer

Increasing fastcgi_read_timeout or proxy_read_timeout is the most common advice for a 504, and it is sometimes correct. It is right when a small number of known, legitimate operations need more time and only trusted users trigger them, such as an administrator running a report. It is wrong as a general fix, because:

If you do raise it, scope it to the path that needs it:

# nginx: longer limit only for the admin export area
location ^~ /admin/exports/ {
    include fastcgi_params;
    fastcgi_param SCRIPT_FILENAME $document_root/index.php;
    fastcgi_pass unix:/run/php/php8.3-fpm-example.sock;
    fastcgi_read_timeout 180s;
}

Remember to raise the matching PHP-FPM request_terminate_timeout for that pool if it is lower, or the worker will be stopped anyway.

Patterns that point to the cause

What you seeLikely cause
Only search results or filtered listings time outQueries with LIKE '%term%' or many filters on unindexed columns
Checkout or contact form times outA payment, email or CRM call with no timeout set on the outgoing request
Everything times out at the same time each nightA backup, import or scheduled task locking tables or using all the disk bandwidth
Timeouts start after the database grewA query that was fine on a small table and now scans millions of rows
Timeouts only during a crawl or traffic spikeWorkers all busy on slow pages, so fast pages queue behind them
Admin pages time out, public pages are fineHeavy dashboard widgets, update checks or uncached reports

Pages that can be cached for anonymous visitors, such as product listings and articles, should be. A full-page cache in front of the application means most requests never reach the slow code at all, which protects the site even while you work on the underlying query.

What 504s mean for search engines

Search engines treat a 504 like other server errors: the page is not fetched, and the crawler tries again later. Repeated timeouts cause Google to slow down its crawling of the site, and slow responses in general reduce how many pages it will request in a session. The Crawl Stats report in Search Console shows both the average response time and the share of requests that ended in server errors, which is a useful before-and-after check once you have made fixes. Slow pages also hurt visitors long before they reach a timeout, so fixing the slow step pays off even for pages that never actually fail.

If your pages respond but only after a long delay, or the connection never gets an answer at all, the request timeout guide covers slow first bytes and network-level causes.

Keeping timeouts away

Questions and answers

1. What does 504 Gateway Timeout mean?

It means a server acting as a go-between, such as nginx, a load balancer or a CDN, forwarded the request to the application behind it and gave up waiting for an answer. The application may still be running the request. The problem is almost always that the page does too much work, waits on a slow database query, or waits on another service, so the fix is to find and speed up that slow step rather than restarting the web server.

2. What is the difference between a 502 and a 504 error?

Both come from a proxy in front of your application. A 502 means the proxy got a broken answer or could not talk to the application at all, often because it crashed or is not running. A 504 means the connection worked, but the application took longer than the proxy was willing to wait. A 502 usually points to a process problem, while a 504 usually points to a slow query, a slow external call or a long-running task.

3. Should I just increase fastcgi_read_timeout or proxy_read_timeout?

Only for specific paths that genuinely need longer, such as an administrator export, and only after checking that the work cannot be made faster or moved to a background job. Raising the limit site-wide means visitors wait longer for pages that are still slow, ties up workers so other pages suffer, and often just moves the error to the CDN or load balancer, whose limit you may not be able to change on your plan.

4. Why do I get a Cloudflare 524 error instead of a 504?

Cloudflare uses 524 when it connected to your server successfully but your server did not send a response within its time limit, which is 100 seconds on most plans. It is the Cloudflare equivalent of a gateway timeout. Your server may still finish the work after Cloudflare gives up. Treat it like a 504: find the slow step on the origin, and move long operations into background jobs rather than expecting the connection to stay open.

5. Why does one slow page cause 504 errors across my whole site?

Your server only has a limited number of workers to handle requests at the same time. If one page takes a minute and several visitors or a crawler request it, those workers stay busy for that whole minute. New requests, even for fast pages, then wait in a queue behind them and run out of time too. Fixing or caching the single slow page, or limiting how often it can run, often clears the site-wide timeouts.

6. How do I find which database query is causing a 504?

Switch on the slow query log in MySQL or MariaDB with a threshold of a couple of seconds, or log_min_duration_statement in PostgreSQL, then trigger the failing page and read the log. The PHP-FPM slow log is also useful, because its stack trace shows which function was running when the request passed its threshold. Once you have the query, run EXPLAIN on it to see whether it scans the whole table and needs an index.

7. Do 504 errors affect my search rankings?

A page that times out cannot be fetched, so it cannot be indexed while it fails. Occasional timeouts are retried by crawlers and rarely matter on their own. Frequent timeouts cause Google to reduce its crawl rate for the site, which slows the discovery of new and updated pages, and pages that fail for a long time can drop out of the index. Slow responses that stop short of a timeout also make crawling less efficient and frustrate visitors.

Find slow and timing-out pages

The HTTP Error Audit requests every URL in your crawl scope, records the status code and response time, follows redirects and flags anything outside the 200 range, so gateway timeouts and slow pages show up together.

Open HTTP Error Fixes โ†’
๐Ÿ’ฌ Got a problem?
Related Guides: All HTTP Error Fixes  ·  502 Bad Gateway Errors  ·  Request Timeout Errors  ·  500 Internal Server Errors  ·  Learning Hub

About aiwebpageseo

aiwebpageseo.com is a data-driven SEO and AEO (Answer Engine Optimisation) platform providing a free suite of technical SEO tools. Rather than relying on AI-theorised assumptions, the platform analyses live URL performance, delivering objective diagnostics, page speed metrics, CLS debugging, and site crawl data alongside actionable technical tutorials.