504 Bad Gateway Error: A Complete Guide to Fixing It

Your site loads fine in one tab, then a checkout page stalls, the browser spins, and you get 504 Bad Gateway. A few minutes later, someone says it works on mobile but fails on desktop. Then your monitoring shows the VPS is up, Nginx is running, and nothing looks obviously broken.

That's where generic advice stops being useful.

A 504 bad gateway error usually means one server in the request path waited too long for another server to answer. The hard part is finding out which hop is timing out. On a VPS, that could be Nginx waiting on PHP-FPM, Apache waiting on an app server, HAProxy waiting on a backend, a CDN waiting on your origin, or a client-side network path behaving differently from another one.

The fastest way to fix it is to debug in layers. Start at the browser and network edge. Move into logs. Check resource pressure. Then change timeout settings only after you know what's slow.

What Is a 504 Bad Gateway Error and Why Does It Happen

A 504 bad gateway error appears when the server you reached first cannot get a timely response from the next server behind it. That definition is straight from the HTTP spec. MDN defines HTTP 504 as a case where a server acting as a gateway or proxy fails to receive a timely response from an upstream server in its HTTP 504 reference.

An infographic explaining a 504 Bad Gateway error, its causes, and a relatable analogy for the user.

The request chain behind the error

On most VPS deployments, the browser doesn't talk directly to your application process. It talks to a front-end service first.

A common chain looks like this:

ComponentRole in the request
BrowserSends the HTTP request
CDN or reverse proxyAccepts the request first
Web serverPasses the request upstream
Application processGenerates the response
Database or APISupplies data to the app

If one upstream step stalls, the layer in front of it eventually gives up and returns 504 to the browser.

That matters because a 504 doesn't automatically mean “the whole server is down”. It often means the front layer is alive enough to tell you the backend is too slow or unreachable.

What usually sits behind the timeout

The cleanest way to think about this is as a queueing problem. One process asks another process for work, then waits. If the answer takes too long, the waiting process stops waiting.

Practical rule: A 504 is usually a symptom at the edge, not the root cause in the core.

Common causes include:

  • An overloaded upstream service that's busy, stuck, or restarting
  • A proxy timeout that's shorter than the work your app is trying to do
  • A dependency delay such as a database query, API call, or file operation
  • A connectivity problem between reverse proxy and backend service
  • A name resolution problem where the proxy can't reliably reach the upstream target

The store-counter analogy works well here. The customer asks the clerk for an item. The clerk goes into the stock room. If the clerk never comes back, the customer doesn't know whether the item is missing, the stock room is blocked, or the clerk got stuck talking to someone else. They only know the wait timed out.

That's exactly why 504 bad gateway issues need methodical debugging. The browser shows the last visible failure. The underlying issue is often one or two layers deeper.

Quick Checks to Rule Out Simple Issues

Before opening config files, prove whether the problem is broad, local, or path-specific. That saves time. It also stops you from changing timeout values when the underlying issue is a desktop firewall, a local proxy, or a CDN path.

A professional woman in a suit interacting with a digital checklist against a colorful watercolor background.

Start with browser and device isolation

A normal refresh re-requests the page. A hard refresh also forces the browser to pull fresh assets instead of leaning on cached content. If the page has stale JavaScript, broken auth state, or a partially cached redirect path, a hard refresh can remove noise from the test.

Use this quick sequence:

  1. Hard refresh the page. In Chromium-based browsers or Firefox, use the browser's hard reload shortcut.
  2. Open a private window. That strips away most stored session state and extensions.
  3. Try a second browser. If Chrome fails but Firefox works, investigate extensions, local proxy settings, or browser security tools.
  4. Try another device. A phone on mobile data is especially useful because it changes both device and network path at once.

One overlooked pattern matters here. There's a documented gap in most 504 guidance when the error happens on desktop but not mobile, even though the backend infrastructure is the same. In a Reddit discussion about 504 on desktop but mobile access working, users describe cases where desktop firewalls or proxy settings block upstream responses while mobile networks bypass those controls.

That's why “it works on my phone” is not a trivial detail. It often means the server is reachable, but one network path is different enough to trigger the timeout.

Check whether the network path is the problem

If desktop fails and mobile works, inspect the local machine before touching the VPS.

Focus on these checks:

  • Corporate proxy settings can redirect traffic through a filtering layer.
  • Endpoint security software may inspect HTTPS traffic and interfere with upstream connections.
  • Local firewall rules can affect browser traffic differently from other apps.
  • VPN clients can change DNS behaviour and outbound routing.

For a clean baseline, disable any optional VPN or local web filtering tool for one test. If the error disappears, you've narrowed the cause to the client path.

If you need a quick refresher on command-line path testing, AvenaCloud's guide on debugging network issues with ping and traceroute is a useful companion while you compare routes from different devices or networks.

Decide what the first five minutes tell you

Use this simple interpretation table:

SymptomLikely direction
Fails on every device and networkServer-side or CDN-side issue
Fails on one desktop onlyLocal browser, firewall, proxy, or DNS cache issue
Fails on office Wi-Fi but not mobile dataNetwork path or ISP filtering difference
Fails only on one URL pathApplication or upstream endpoint issue
Fails intermittently under loadResource pressure, queueing, or timeout mismatch

If one path works and another doesn't, don't start by increasing server timeouts. First prove whether the requests are even reaching the same stack in the same way.

Finding Clues in Server Logs and Performance Metrics

Once you know the problem isn't just a local browser or network quirk, the terminal becomes the fastest way forward. A 504 bad gateway problem leaves clues in logs far more often than it leaves clues in the browser.

Read the web server logs first

On a Linux VPS, start with the active web server and work inward.

For Nginx, common log locations are:

  • /var/log/nginx/error.log
  • /var/log/nginx/access.log

Useful commands:

sudo tail -n 50 /var/log/nginx/error.log
sudo tail -f /var/log/nginx/error.log
sudo grep -i "upstream timed out" /var/log/nginx/error.log
sudo grep -i "connect() failed" /var/log/nginx/error.log

For Apache, check:

  • /var/log/apache2/error.log on many Debian-based systems
  • /var/log/httpd/error_log on many RHEL-based systems

Commands:

sudo tail -n 50 /var/log/apache2/error.log
sudo tail -f /var/log/apache2/error.log
sudo grep -i "proxy" /var/log/apache2/error.log
sudo grep -i "timeout" /var/log/apache2/error.log

If your app uses PHP-FPM, don't stop at the web server. Check the PHP-FPM logs too. Depending on distro and pool config, you may find them in the PHP version directory under /var/log or in the system journal.

sudo journalctl -u php-fpm -n 100 --no-pager
sudo journalctl -u php8.2-fpm -n 100 --no-pager

When you see phrases like upstream timed out, that usually means the front-end web server accepted the client request but the backend process didn't answer quickly enough. When you see connect() failed, the web server may not be able to reach the backend socket or service at all.

Correlate errors with the exact request

Don't read logs in isolation. Trigger the failing page, then inspect the fresh lines immediately.

This pattern works well:

sudo tail -f /var/log/nginx/error.log /var/log/nginx/access.log

Load the failing URL in a browser or with curl from another shell:

curl -I http://localhost

If the request fails externally but works locally on the VPS, your origin may be healthy while the issue sits in the CDN, firewall, or external routing layer. If it fails locally too, keep moving inward.

A more targeted grep helps when logs are noisy:

sudo grep " 504 " /var/log/nginx/access.log | tail -n 20

Look for patterns such as one endpoint failing repeatedly, requests clustering around deployments, or only dynamic routes returning 504 while static assets stay fast.

For a wider workflow on interpreting VPS logs, AvenaCloud's article on analysing VPS logs for better performance insights gives a useful structure for sorting signal from noise.

Check whether the VPS is simply under pressure

A server can be “up” and still be too busy to answer upstream requests on time.

Start with the basic resource tools:

top

If available, htop is easier to read:

htop

Check memory usage:

free -m

Check disk space and mounted filesystems:

df -h

Three conditions often line up with 504 bad gateway incidents:

  • CPU saturation. Worker processes are runnable but not getting enough CPU time.
  • Memory pressure. The kernel starts reclaiming aggressively or swapping, which slows app response.
  • Disk contention. Logging, temp files, or database activity stalls the app path.

Field note: If load spikes at the same moment 504s appear, raising the proxy timeout may only hide the bottleneck. The request is still slow. You're just waiting longer to prove it.

Distinguish timeout from crash

A timeout and a crash can look similar from the browser, but the fix is different.

Use this checklist:

What you seeWhat it often means
upstream timed outBackend responded too slowly
connection refusedBackend service is down or listening elsewhere
Repeated worker restartsApp or PHP-FPM instability
504 only on expensive endpointsSlow query, external API, or heavy computation
High CPU with no clear errorsQueueing, contention, or inefficient code path

If the service manager shows restarts or failures, inspect it directly:

sudo systemctl status nginx
sudo systemctl status apache2
sudo systemctl status php8.2-fpm
sudo systemctl status haproxy

The goal here isn't to collect every log line. It's to answer one specific question: what component waited, and what was it waiting on? Once you know that, timeout tuning becomes precise instead of hopeful.

How to Adjust Server and Proxy Timeout Settings

Changing timeout values can fix a real 504 bad gateway problem, but only when the request is valid and just needs more time. If the backend is hung, unreachable, or overloaded, larger numbers only delay the failure.

That's why timeout tuning should follow log review, not replace it.

A comparison table showing how to adjust server and proxy timeout settings for Nginx and Apache web servers.

Nginx timeout settings that matter

If Nginx sits in front of your app, four directives show up constantly in 504 investigations:

  • proxy_connect_timeout
  • proxy_send_timeout
  • proxy_read_timeout
  • send_timeout

The default Nginx timeout for API requests is 60 seconds, and one commonly used fix is to set those timeout directives to 240 seconds in nginx.conf, as noted in this Stack Overflow discussion on fixing a 504 gateway timeout.

A typical Nginx block looks like this:

http {
    proxy_connect_timeout 240;
    proxy_send_timeout 240;
    proxy_read_timeout 240;
    send_timeout 240;
}

Or inside a specific server or location block:

server {
    listen 80;
    server_name example.test;

    location / {
        proxy_pass http://app_backend;
        proxy_connect_timeout 240;
        proxy_send_timeout 240;
        proxy_read_timeout 240;
        send_timeout 240;
    }
}

What each setting controls:

DirectiveWhat it affects
proxy_connect_timeoutHow long Nginx waits to connect to the upstream
proxy_send_timeoutHow long Nginx waits while sending request data upstream
proxy_read_timeoutHow long Nginx waits for the upstream response
send_timeoutHow long Nginx allows for sending the response to the client

After editing config, always test before reloading:

sudo nginx -t
sudo systemctl reload nginx

If you run Nginx as a reverse proxy on a VPS, AvenaCloud's guide on setting up an Nginx reverse proxy for faster performance is useful background for structuring upstream blocks cleanly.

Apache and mod_proxy timeout tuning

Apache throws 504s in similar ways when it proxies to another service. The directive many admins start with is ProxyTimeout.

A basic example:

<VirtualHost *:80>
    ServerName example.test

    ProxyPreserveHost On
    ProxyPass / http://127.0.0.1:8080/
    ProxyPassReverse / http://127.0.0.1:8080/

    ProxyTimeout 300
</VirtualHost>

Then reload or restart Apache after a config test:

sudo apachectl configtest
sudo systemctl restart apache2

ProxyTimeout tells Apache how long to wait for a proxied response. If a backend app consistently takes longer than Apache allows, the browser sees a 504 even though the app might still be working in the background.

Apache can also time out because of related settings outside the virtual host, depending on module stack and distro defaults. When Apache is the front layer, inspect global timeout values alongside any proxy-specific ones.

HAProxy and backend wait limits

HAProxy is often clearer than web servers about where the delay lives, but you still need to set sensible backend limits.

A basic backend example:

defaults
    mode http
    timeout connect 30s
    timeout client  60s
    timeout server  60s

frontend http_front
    bind *:80
    default_backend app_back

backend app_back
    server app1 127.0.0.1:8080 check

If your logs show the backend regularly needs more time and that behaviour is expected, increase timeout server carefully:

defaults
    mode http
    timeout connect 30s
    timeout client  120s
    timeout server  120s

Then validate and reload:

sudo haproxy -c -f /etc/haproxy/haproxy.cfg
sudo systemctl reload haproxy

HAProxy is powerful because you can see whether the wait is on connect, queue, or server response. If queueing is the issue, increasing timeout server alone may not help. You may need more backend workers or a less expensive request path.

Application limits often cause the real timeout

Many 504 fixes fail due to the application worker exiting early or getting killed by its own runtime limits, even with an increased proxy timeout.

For PHP applications, inspect:

  • PHP max_execution_time
  • PHP-FPM pool settings
  • PHP-FPM request_terminate_timeout

If a PHP process is terminated before Nginx or Apache gets a valid response, the proxy can only report the symptom.

A PHP-FPM pool file may include something like:

request_terminate_timeout = 240s

And PHP configuration may include:

max_execution_time = 240

After changes:

sudo systemctl reload php8.2-fpm

Match the stack from app outward. If PHP-FPM kills the request at one limit, Apache waits longer, and the CDN waits shorter, you create inconsistent behaviour and harder debugging.

Don't tune just the front door. Tune the whole request chain so every layer agrees on how long legitimate work may take.

What works and what usually doesn't

Use timeout increases when:

  • the endpoint is valid but occasionally slow
  • logs show the upstream does answer, just later than the current limit
  • the delay comes from known heavy operations that you can't redesign immediately

Don't rely on timeout increases when:

  • the backend process is dead or unreachable
  • CPU or memory pressure is severe
  • a database query or external API call is hanging
  • long-running work should be moved to a background queue instead of HTTP

A practical pattern for jobs such as report generation, exports, media processing, or AI inference is to accept the request quickly, enqueue the heavy work, and let the client poll for status or receive a completion callback. That design removes the pressure to stretch every timeout in the stack.

Resolving CDN Firewall and Connectivity Problems

A 504 bad gateway error doesn't always originate on your VPS. If you use a CDN or reverse proxy service, that layer can generate the error while your origin server is still running.

A direct diagnostic step is often faster than speculation. Elementor notes that CDN services such as Cloudflare can trigger 504 errors because of maintenance or gateway latency, and recommends temporarily enabling Development Mode or pausing the CDN so traffic routes directly to the hosting server in its guide to 504 gateway timeout errors.

Test the origin without the CDN in front

If pausing the CDN or switching to Development Mode makes the site load normally, you've isolated the problem to the CDN layer, the CDN-to-origin path, or a policy between them.

Use this interpretation:

Test resultLikely cause
Site works when CDN is bypassedCDN layer, origin reachability, or caching/proxy policy
Site still fails when CDN is bypassedOrigin-side app, proxy, or server issue
Static files work but dynamic pages failOrigin app latency or upstream timeout
Only some regions failEdge routing or path-specific connectivity

This test matters because many admins spend time editing Nginx when the edge proxy is the component returning 504 first.

Inspect firewall rules with the request path in mind

Firewalls can break upstream communication in ways that look like slow application behaviour. A front-end service can accept the request, try to connect to the next hop, then sit until timeout because a port, interface, or local policy blocks the traffic.

Check these layers:

  • Host firewall on the VPS, such as ufw, firewalld, or direct iptables rules
  • Reverse proxy policy that limits which upstreams are reachable
  • Cloud firewall controls in the hosting panel
  • Service-to-service rules if app components are split across containers or internal interfaces

The useful question isn't “is the firewall on?” It's “does this specific process have a clear path to this specific upstream service?”

For a structured review, AvenaCloud's article on checking the proxy and the firewall is a practical checklist when you need to validate whether traffic is being blocked before it reaches the backend.

Confirm local connectivity from the VPS itself

Run tests from the server, not just from your laptop. If Nginx proxies to an app on another local port or internal service, verify that path directly from the VPS shell.

Examples:

curl -I http://localhost

If your app listens on a different local port, query that local endpoint from the same machine. If the local request hangs or fails while the web server process waits on it, you're no longer looking at a browser issue. You're looking at an origin-side connectivity or service health problem.

A clean CDN bypass test can save hours. If the site works direct to origin, stop tuning PHP first and inspect the edge path.

Proactive Strategies to Prevent 504 Errors

The best fix for 504 bad gateway incidents is to stop treating them as isolated browser errors. They're usually latency problems that became visible only when a timeout threshold was crossed.

That matters even more in modern workloads. Statsig reports that 504 errors are increasingly triggered by microservice latency spikes in AI/ML and big data workloads, with that trend rising 35% in the last 12 months as cloud providers scale GPU instances in its analysis of gateway timeout diagnosis and enterprise solutions. Generic WordPress-era advice doesn't cover that well.

Build for latency visibility

If you wait until users report 504s, you're already late.

A better operating model includes:

  • Request timing at the proxy so you can see whether delay happened before connect, during upstream wait, or while sending the response
  • Application timing logs around slow code paths, external API calls, and database operations
  • Basic host monitoring for CPU, memory, disk pressure, and process restarts
  • Alerting on rising latency, not just on hard downtime

The key is correlation. When response times climb, you want to know whether the bottleneck lives in app code, a worker pool, a queue, a dependency, or the network path between services.

Move heavy work out of the request cycle

Stretching HTTP timeouts is sometimes necessary, but it's rarely the long-term design you want.

For jobs that can run asynchronously, use a queue and return quickly. That applies to:

  • report generation
  • bulk imports
  • media transcoding
  • product feed builds
  • long inference tasks
  • expensive cache rebuilds

This reduces request contention and keeps the proxy stack serving normal traffic while heavier work completes separately.

Treat microservices and AI workloads differently

Microservice-heavy stacks fail differently from simple CMS sites. A single user request might traverse several services before a response comes back. If one service slows down, every service upstream inherits that delay.

For AI/ML and streaming workloads, don't assume more CPU or RAM alone will clear the problem immediately. Queueing, contention, and upstream dependency timing often matter more than raw instance size in the moment. Trace service-to-service latency, inspect worker concurrency, and be deliberate about where long-running inference work is allowed to happen.

The durable fix for 504 bad gateway errors isn't “wait longer”. It's “know where the time goes”.

A 504 should push you to improve observability, isolate dependencies, and redesign slow request paths where possible. When teams do that, timeout tuning becomes a finishing step, not the whole strategy.


If you need VPS infrastructure that gives you root access, clean scaling options, and the flexibility to tune Nginx, Apache, HAProxy, PHP-FPM, and modern app stacks properly, AvenaCloud Hosting Provider is worth a look. It's a practical fit for teams running websites, APIs, e-commerce platforms, and heavier AI or data workloads that need predictable server control instead of one-size-fits-all hosting.

Related Posts