A 504 Gateway Timeout means an intermediary server – a reverse proxy, load balancer, or CDN – waited for a response from an upstream server and gave up before one arrived. The intermediary is working fine. The problem is behind it: something upstream is too slow, stuck, or unreachable.
This is different from a 503 Service Unavailable, which is an immediate refusal. A 504 is a timeout – the upstream accepted the connection (or at least did not refuse it) but never finished responding. The intermediary waited as long as its configuration allows, then returned a 504 to the client.
What the HTTP specification says#
HTTP 504 is defined in RFC 9110, Section 15.6.5. The specification says the server, while acting as a gateway or proxy, did not receive a timely response from an upstream server it needed to access in order to complete the request.
The key phrase is “acting as a gateway or proxy.” A 504 only comes from a server that sits between the client and the actual application server. If you are connecting directly to an application and it times out, you would see a connection timeout or a 500 Internal Server Error, not a 504.
HTTP/1.1 504 Gateway Timeout
Server: cloudflare
Content-Type: text/html
The
Server
header tells you which layer generated the 504. This is the first thing to check when diagnosing the problem.
The request chain and where timeouts happen#
A typical web request passes through multiple layers, and a 504 can originate at any intermediary:
Browser -> CDN -> Load Balancer -> Web Server -> Application Backend -> Database
Each arrow is a connection with its own timeout. A 504 occurs when any intermediary in this chain gives up waiting for the next server to respond:
- CDN times out waiting for your origin server (Cloudflare, CloudFront, Fastly)
- Load balancer times out waiting for a backend server (AWS ALB, HAProxy, Nginx upstream)
- Web server times out waiting for the application backend (Nginx waiting for PHP-FPM, Apache waiting for mod_php or a WSGI process)
- Application times out waiting for a database, external API, or microservice
Each layer has its own timeout configuration. The shortest timeout in the chain determines when the 504 fires. If your CDN has a 30-second timeout and your web server has a 60-second timeout, the CDN will give up before the web server does, and the client sees a 504 from the CDN.
Common causes of a 504#
Slow application code
The most frequent cause. The application is processing the request but taking longer than the proxy’s timeout allows. Common culprits:
- A database query scanning millions of rows without an index
- An N+1 query pattern loading hundreds of related records individually
- A page builder or plugin running expensive operations on every page load
- Generating a large report, export, or sitemap
- An infinite loop or deadlock in application code
The application is not down – it is working, just too slowly. If you could wait long enough, the response would eventually arrive. But the proxy gives up before that happens.
Slow or unresponsive database
The application connects to the database and sends a query, but the database takes too long to return results. This can happen because:
- A query is waiting for a lock held by another transaction
- The database server is overloaded with concurrent queries
- A table is missing an index and the query is doing a full table scan
- The database server is running out of memory and swapping to disk
- A long-running backup or maintenance operation is consuming resources
For WordPress specifically, MySQL connection issues and unoptimized databases are the most common database-related causes of 504 errors.
External API calls
Your application makes an HTTP request to a third-party service – a payment gateway, email provider, geocoding API, or social media platform – and that service is slow or down. The application blocks waiting for the response, and the proxy times out waiting for the application.
This is especially common with:
- Payment processing during checkout (WooCommerce, Shopify)
- REST API calls to CRM or marketing automation platforms
- DNS lookups for external services when the resolver is slow
- Webhook deliveries that trigger synchronous processing
PHP-FPM and application backend timeouts
On WordPress and PHP-based sites, the web server (usually Nginx) passes requests to PHP-FPM. If a PHP script runs longer than the proxy timeout, Nginx returns a 504. The PHP process may still be running in the background after Nginx gives up – it does not know the client has already received an error.
This is the most common 504 scenario on WordPress hosting. For Nginx-specific diagnosis and fixes, see 504 Gateway Timeout in Nginx.
CDN-to-origin connectivity issues
If your site is behind a CDN like Cloudflare, the 504 may come from the CDN rather than your web server. The CDN connects to your origin server, and if your origin is slow, overloaded, or has network issues, the CDN times out.
Cloudflare’s default timeout for free plans is 100 seconds. If your origin takes longer than that to respond, Cloudflare returns a 504 with its own error page. The origin server may be working fine for direct connections but timing out through the CDN because of the additional network hop.
CDN-generated 504 errors are distinguishable by the
Server: cloudflare
header (or equivalent for your CDN). See 520 and 521 web server errors for related CDN-to-origin communication failures.
Resource exhaustion
The server has run out of a critical resource:
- Memory – the application or database is swapping to disk, making everything slow
- CPU – the processor is at 100% and requests are queuing
- Disk I/O – a backup, import, or heavy write operation is saturating the disk
- Network – bandwidth is saturated or there is packet loss between servers
- Connection pool – the application has exhausted its database or HTTP connection pool
Resource exhaustion turns normally fast operations into slow ones, pushing them past timeout thresholds.
How to diagnose a 504#
Identify which layer timed out
The
Server
header in the 504 response tells you which intermediary gave up:
curl -I https://example.com/slow-page
| Server header | The 504 came from |
|---|---|
cloudflare
| Cloudflare CDN |
CloudFront
| AWS CloudFront |
nginx
| Your Nginx web server |
Apache
| Your Apache web server |
awselb/2.0
| AWS Application Load Balancer |
If the 504 comes from the CDN, the problem could be anywhere between the CDN and your application. If it comes from your web server, the problem is between the web server and the application backend.
Check error logs
Each layer in the chain has its own error log:
Web server (Nginx):
tail -f /var/log/nginx/error.log
A Nginx 504 typically shows:
upstream timed out (110: Connection timed out) while reading response header from upstream
Application (PHP-FPM):
tail -f /var/log/php-fpm/error.log
Application (WordPress): Enable debug logging in wp-config.php:
define('WP_DEBUG', true);
define('WP_DEBUG_LOG', true);
define('WP_DEBUG_DISPLAY', false);
Then check
wp-content/debug.log
for slow queries or errors.
Determine the scope
- One specific page or action – that page triggers a slow operation (heavy query, external API call, large export)
- All pages intermittently – the server is near capacity and occasionally tips over the timeout threshold
- All pages consistently – the backend is down, stuck, or severely overloaded
- Only through the CDN – the CDN-to-origin connection has issues, but direct access works
Check server resources
If you have SSH access:
# CPU and memory
top -bn1 | head -20
# Disk I/O
iostat -x 1 5
# Available memory
free -m
# Disk space
df -h
# MySQL process list (find stuck queries)
mysql -u root -p -e "SHOW PROCESSLIST;"
Look for processes consuming excessive CPU, memory pressure causing swap usage, or MySQL queries that have been running for an unusually long time.
Test with extended timeouts
If you can curl directly to your origin server (bypassing the CDN), you can set a longer timeout to see if the request eventually completes:
curl -o /dev/null -w "Time: %{time_total}s, Status: %{http_code}\n" \
--max-time 300 https://your-origin-ip/slow-page \
-H "Host: example.com"
If the request completes in 90 seconds but your CDN timeout is 60 seconds, you know the request works – it is just too slow for the proxy timeout.
How to fix a 504#
If a specific page or action is timing out
The problem is that page’s code. Find what is slow and fix it:
- Slow database queries – add missing indexes, optimize the query, or clean up the database. For WordPress, the Query Monitor plugin identifies exactly which queries are slow and which plugin triggered them.
- External API calls – add a timeout to the HTTP request so it fails fast instead of blocking forever. Set a 5-10 second timeout on outbound API calls and handle the timeout gracefully.
- Heavy computation – move it to a background job instead of doing it during the page request. WordPress has
wp_schedule_single_event()for deferred processing; Node.js has Bull queues; most frameworks have a background job system. - Large imports or exports – process them in batches rather than all at once.
If all pages are slow
The problem is at the server level:
- Check PHP-FPM – are all workers busy? If the PHP-FPM pool is exhausted, requests queue and eventually time out. This produces 504s across the board.
- Check the database – run
SHOW PROCESSLISTin MySQL. If you see dozens of queries in aLockedorSending datastate, the database is the bottleneck. - Check memory – if the server is swapping (
free -mshows swap usage), everything slows down. Either reduce memory consumption or increase server resources. - Check for bot traffic – bots hammering expensive PHP endpoints consume workers and database connections. Check access logs for high-volume IPs hitting dynamic pages. Rate limiting and bot detection can prevent bots from starving real visitors of resources.
If the 504 comes from the CDN
The fix depends on why the origin is slow:
- Fix the origin – if the origin server is genuinely slow, no amount of CDN timeout tuning will help. Fix the underlying performance issue.
- Enable caching – if the CDN can serve the response from cache, it never needs to contact the origin. Configure appropriate cache headers for static and semi-static content.
- Increase CDN timeout – some CDN plans allow longer origin timeouts. Cloudflare Pro and Business plans allow up to 6000 seconds for certain endpoints. This is a band-aid, not a fix.
- Check the origin firewall – verify the CDN’s IP ranges are allowed through your firewall. If some CDN IPs are blocked, requests from those nodes time out while others succeed, producing intermittent 504s.
Adjusting timeout settings
Increasing timeouts is a valid short-term fix but should not be the long-term solution. A request that takes 120 seconds is holding a worker process for 120 seconds – that worker cannot serve other visitors during that time.
If you do need to increase timeouts, you must adjust every layer in the chain. Increasing the web server timeout without increasing the CDN timeout means the CDN will still give up first.
Nginx:
proxy_read_timeout 120s;
proxy_connect_timeout 10s;
proxy_send_timeout 120s;
fastcgi_read_timeout 120s;
Apache:
ProxyTimeout 120
TimeOut 120
PHP:
max_execution_time = 120
The general rule: CDN timeout > web server timeout > application timeout. If the application is allowed 120 seconds, the web server should wait at least 130, and the CDN at least 140. Otherwise, the shorter timeout fires first and the longer ones serve no purpose.
504 vs other 5xx errors#
| Status code | What happened | The upstream… |
|---|---|---|
| 500 Internal Server Error | The server crashed or hit an unhandled error | failed during execution |
| 502 Bad Gateway | The proxy got an invalid response | responded, but the response was broken |
| 503 Service Unavailable | The upstream refused the connection | is down or overloaded (immediate refusal) |
| 504 Gateway Timeout | The proxy gave up waiting | is running but too slow to respond in time |
The key difference between 502 and 504: a 502 means the upstream did respond, but the response was invalid or the connection was reset mid-response. A 504 means the upstream never responded at all within the timeout window.
The key difference between 503 and 504: a 503 is immediate – the upstream says “no” right away. A 504 is a timeout – the upstream says nothing, and the proxy eventually gives up. Both can result from server overload, but they indicate different failure modes. If the backend’s request queue is full and it rejects immediately, you get a 503. If the request enters the queue but never gets processed in time, you get a 504.
504 and SEO#
Search engines treat a 504 similarly to a 503 – as a temporary condition. A brief 504 during a traffic spike or deployment will not affect your rankings. But persistent 504 errors will:
- Reduce crawl rate – Googlebot backs off when it encounters repeated timeouts, meaning new and updated content gets indexed more slowly
- Drop pages from the index – if Googlebot consistently gets 504 on specific URLs, those pages will eventually be removed from search results
- Affect Core Web Vitals – while a 504 itself is not a CWV metric, the slow responses that cause 504s also hurt Time to First Byte (TTFB) for requests that do complete
Monitor your 504 rate in your server logs and Google Search Console. A spike in 504 errors correlates with a drop in crawl rate, which you can see in Search Console under Settings > Crawl stats.
What to tell your hosting provider#
If you cannot resolve the 504 yourself, provide your hosting provider with:
- The exact URL(s) that time out (is it one page or all pages?)
- When the timeouts started and whether they are constant or intermittent
- Whether the site works when bypassing the CDN (direct IP access)
- Any recent changes – new plugins, traffic spikes, database changes
- The response headers from the 504 response (especially the
Serverheader) - Results from
top,free -m, orSHOW PROCESSLISTif you have SSH access
The more specific you can be about which layer is timing out and what changed, the faster the support team can identify the root cause.
Summary#
A 504 Gateway Timeout means a proxy or intermediary waited for an upstream server and gave up before receiving a response. The problem is almost always behind the proxy – a slow application, an overloaded database, a stuck external API call, or resource exhaustion on the server.
Diagnose by identifying which layer generated the 504 (check the
Server
header), then work backward through the chain to find the slow component. Fix the root cause rather than increasing timeouts – a request that takes two minutes is a symptom, not a baseline.
For Nginx-specific 504 troubleshooting, see 504 Gateway Timeout in Nginx. For related errors, see HTTP 503 Service Unavailable, 502 Bad Gateway, and HTTP 500 Internal Server Error.