A Cloudflare 502 means Cloudflare could not get a valid response from your origin server, and the most useful first step is not “look at the error code” — it is to figure out which of the three places a 502 actually comes from. It can come from your origin (most common), from Cloudflare itself (rare, often transient), or from a Cloudflare Tunnel between the two (the case the documentation buries). Each one has a different fix, and the wrong fix on the wrong cause is the most common reason a 502 stays up for hours.
Most blog posts about the Cloudflare 502 give you a checklist of six things to try. That works for the first ten minutes. After the first ten minutes, the team needs a way to tell which of the three places the 502 is actually firing, because the fix for a 502 from the origin is restart the origin, the fix for a 502 from Cloudflare is wait, and the fix for a 502 from a tunnel is check the tunnel config. The right fix depends on the right diagnosis.
Table of contents
- The 30-second diagnostic: is the 502 from the origin, Cloudflare, or a tunnel?
- Case 1: the 502 is from your origin server
- Case 2: the 502 is from Cloudflare itself
- Case 3: the 502 is from a Cloudflare Tunnel
- The five things to check in order (the actual checklist)
- When the 502 only happens on a specific URL or path
- When the 502 only happens with specific HTTP methods
- When the 502 is real and not a Cloudflare edge hiccup
- How to set up a 502 alarm so you do not find out from a customer
- FAQ
The 30-second diagnostic: is the 502 from the origin, Cloudflare, or a tunnel?
Open <YOUR_DOMAIN>/cdn-cgi/trace in a browser. The page returns a plain-text dump with the request’s path through the Cloudflare network. Look at the top of the output:
fl=xxx
h=yourdomain.com
ip=...
ts=...
visit_scheme=https
uag=...
colo=...
http=http/2
loc=...
tls=TLSv1.3
sni=encrypted
warp=off
gateway=off
rbi=off
kex=X25519
The colo= line tells you which Cloudflare data center served the request. The http= line tells you the protocol. None of those by themselves say “origin 502” or “Cloudflare 502.” The 502 itself does not appear in the trace.
The trick is to compare two checks at the same time.
Check A: load the origin directly. If your domain is app.example.com and the origin is origin.example.com, load https://origin.example.com in a browser (or curl -I https://origin.example.com). If the origin returns a 502 too, the problem is at the origin. If the origin returns 200, the problem is between Cloudflare and the origin.
Check B: check the Cloudflare status page. Open https://www.cloudflarestatus.com/. If Cloudflare is reporting an incident at the colo from your trace, the 502 is from Cloudflare’s edge and will resolve when the incident resolves.
Check C: if you are using Cloudflare Tunnel, check cloudflared. Run cloudflared tunnel info <tunnel-name> on the host that runs the tunnel. If the tunnel is connected but the origin service is unreachable, the 502 is from the tunnel. The error message in cloudflared will say exactly that: “Unable to reach the origin service.”
The three checks take 30 seconds. The three answers point to three different fixes, which is the rest of this post.
Case 1: the 502 is from your origin server
This is the most common case. Cloudflare shows a Cloudflare-branded 502 page (white background, Cloudflare logo, “the web server reported a bad gateway error”). The origin is returning a real 502 to Cloudflare, and Cloudflare is passing it through.
The fix is on the origin. The causes are the boring ones:
The origin process is down. Check the host. systemctl status nginx (or caddy, apache, whatever serves the app). If the process is not running, start it. If the process is running but not listening, check the port. If the process is listening but refusing connections, check the firewall.
The origin is overloaded. CPU at 100%, memory at 100%, the database connection pool exhausted. The fix is to scale the origin (add capacity, scale out, or move the workload). For a single-host setup, the fix is to restart the origin and look at the metrics to find the leak. For a managed application platform like RunxBuild, the fix is usually to scale the service up or out and let the platform handle the rest.
The origin timed out. Cloudflare waits up to 100 seconds for the origin. If the origin does not respond in 100 seconds, Cloudflare returns a 504 (gateway timeout), not a 502, but a 502 from a slow origin is also possible if the origin returns a partial response that the proxy rejects. The fix is to make the origin faster or to set a lower Cloudflare timeout.
The origin is responding with broken compression. Cloudflare expects the Content-Length header to match the actual response body. If the origin sends Content-Length: 1000 but the gzipped body is 800 bytes, Cloudflare rejects the response with a 502. The fix is to fix the origin’s compression (or disable it at the origin and let Cloudflare handle compression at the edge).
For a managed deploy, the most common cause of a 502 from the origin is the database. The application is up, the application process is running, but the database is unreachable, and the application’s health check is failing because the database is unreachable. The 502 in this case is correct — the application is unhealthy. The fix is the database, not the application. Check the database connection and the managed Postgres status before restarting the application.
Case 2: the 502 is from Cloudflare itself
This is the rare case. Cloudflare shows an unbranded 502 page (no Cloudflare logo, plain text). The origin is up. The cloudflarestatus.com page may or may not show an incident.
Three common causes.
A Cloudflare data center is having a bad day. Cloudflare runs traffic through 300+ data centers, and a single data center can have a transient failure. The 502 in this case affects only the requests that landed on the bad data center. The fix is to wait. Cloudflare’s automated traffic management will redirect the affected traffic to a healthy data center within seconds. Reload the page, get a 200, move on.
A compression mismatch on Cloudflare’s edge. Cloudflare can be configured to compress responses at the edge. If the origin is also compressing the response, the two compression layers can produce a malformed response that Cloudflare rejects with a 502. The fix is to disable one of the two compressors. The Cloudflare-side compressor is in the Speed > Optimization tab. The origin-side compressor depends on the origin (nginx gzip on;, Apache mod_deflate, etc.).
An early-hints cache miss. Cloudflare’s Early Hints feature preloads resources before the main response arrives. A cache miss on Early Hints can produce a 504, not a 502, but the symptom looks similar. The fix is to disable Early Hints or to accept the benign 504s in logs.
For Case 2, the diagnostic test is the origin-direct test from Check A above. If the origin is up, the 502 is from Cloudflare. The fix is either to wait, disable a feature, or contact Cloudflare support with the timestamp, the URL, and the cdn-cgi/trace output.
Case 3: the 502 is from a Cloudflare Tunnel
This is the case the documentation buries. If you are running a Cloudflare Tunnel (cloudflared), the 502 from the browser can come from a third place: the tunnel connection between Cloudflare’s edge and the cloudflared instance on your network.
The diagnostic is the tunnel log. Run:
cloudflared tunnel info <tunnel-name>
The output shows the connection status. A healthy tunnel says “connected to
For a connected tunnel that is returning 502s, the cause is between cloudflared and the origin service. The error message in the cloudflared log will say:
ERR Unable to reach the origin service. The service may be down or it may not be responding to traffic from cloudflared. error="..."
The most common causes:
The origin service is down. The application is not running on the host. Restart the service. If the service is managed by a process supervisor (systemd, supervisord, s6), check the supervisor logs.
The origin is on a different port than the tunnel config says. The tunnel config defines the destination as http://localhost:8080 and the application is on port 3000. Fix the config. The fix is one line in the config.yml file.
The origin is on HTTPS but the tunnel is configured for HTTP. The tunnel connects to https://localhost:8443 but the application is serving HTTP. Either change the tunnel to http:// or set up a TLS certificate on the origin. The Cloudflare Tunnel docs cover this in the “Origin” section.
The origin is bound to 127.0.0.1 and the tunnel is on a different host. If cloudflared is on host A and the application is on host B, the tunnel’s http://localhost:8080 resolves to host A. The application is on host B. The fix is to point the tunnel at the right host: http://host-b:8080.
The origin SSL is set to “Full” but the certificate is self-signed. The Cloudflare SSL/TLS setting “Full” verifies the origin’s certificate. A self-signed certificate will fail the verification. The fix is either to set the SSL mode to “Full (Strict)” and install a real certificate, or to set the SSL mode to “Flexible” and accept the lack of verification.
For a production deploy on a managed platform, the Cloudflare Tunnel setup is usually a separate cloudflared instance in front of the platform’s load balancer. The most common cause of a tunnel 502 in this setup is the platform restarting the application. The restart takes 5-10 seconds, and the tunnel reports a 502 for that window. The fix is to set the tunnel to retry on connection failure, which cloudflared does by default but with a short retry window.
The five things to check in order (the actual checklist)
A real production incident is not the time to think. The checklist below is the order to check in, the time each step takes, and the next step if the check fails.
-
Open
https://www.cloudflarestatus.com/and check the colo from your/cdn-cgi/trace. Takes 10 seconds. If there is an incident at your colo, the 502 is from Cloudflare’s edge. The fix is to wait for the incident to resolve. If there is no incident, move to step 2. -
Load the origin directly (
curl -I https://origin.example.com). Takes 5 seconds. If the origin is returning a 502, the problem is the origin. The fix is on the origin host. If the origin is returning 200, move to step 3. -
If you are using Cloudflare Tunnel, check the tunnel status (
cloudflared tunnel info <name>). Takes 5 seconds. If the tunnel is disconnected, the fix is to restartcloudflared. If the tunnel is connected and the origin is up but you are still seeing 502, move to step 4. -
Check the origin logs for the last 5 minutes. Takes 30 seconds. Look for the 502-producing request. If the origin is a web server, the log line will show the request and the response. If the origin is a Node.js or Python application, the log line will show the exception that caused the 502. The exception is the fix. If the logs are empty, move to step 5.
-
Check the Cloudflare firewall and WAF rules for the requesting IP. Takes 30 seconds. A misconfigured WAF rule can produce a 502 for legitimate traffic if the rule is malformed. The fix is to disable the WAF rule, retest, and re-enable the rule with the correct syntax.
The five checks together take about 90 seconds. The 90 seconds are the most valuable 90 seconds in any Cloudflare 502 incident, because the order is the part that matters. The first check that distinguishes the three cases (origin, Cloudflare, tunnel) is the one that tells you which fix to apply.
When the 502 only happens on a specific URL or path
The most common cause is the origin’s routing layer. nginx, for example, will return a 502 when the upstream (proxy_pass) target is unreachable. The fix is to check the nginx config for the specific path and confirm the upstream is up.
The second most common cause is a path that triggers a heavy operation in the application — a long-running report, a database query that hits an unindexed table, a third-party API call that times out. The 502 in this case is the application giving up on the operation. The fix is to make the operation faster, paginate it, or push it to a background job.
The third most common cause is a URL that includes special characters or non-ASCII characters that the origin’s URL parser rejects. The fix is to URL-encode the path before sending the request, and to confirm the origin’s URL parser accepts the encoded form.
For a managed application platform like RunxBuild, the most common cause of a path-specific 502 is the application timing out on a specific operation while other paths serve 200s. The platform’s health check will mark the application unhealthy if the timeout happens on a health-checked path. The fix is to either increase the timeout (if the operation is legitimate) or move the operation to a worker that does not block the main response.
When the 502 only happens with specific HTTP methods
The cause is almost always a Cloudflare WAF rule or a rate limit. POST and PUT requests are more likely to hit a WAF rule than GETs, and 502s from WAF rules are common in misconfigured setups.
The diagnostic is to test the same path with GET, then with POST. If GET works and POST returns 502, the WAF rule on POST is the cause. The fix is to either adjust the WAF rule or to bypass the WAF for the specific endpoint.
The second most common cause is a CORS preflight. The browser sends an OPTIONS request before the actual request, and the origin’s CORS handler returns 502 because the preflight is malformed. The fix is to set the Access-Control-Allow-* headers correctly in the origin and to handle the OPTIONS method.
When the 502 is real and not a Cloudflare edge hiccup
A real 502 is a 502 you can reproduce. The way to reproduce it is to load the same URL from a different network (your phone on cellular, a coworker on a different wifi, curl from a different host). If every request returns 502, the 502 is real. If only some requests return 502, the 502 is intermittent and the cause is upstream (Cloudflare’s edge or a network between you and Cloudflare).
For an intermittent 502, the cause is one of three things:
A network blip between Cloudflare and the origin. This is more common on long-distance origin connections (Cloudflare edge in Asia to origin in the US). The fix is either to accept the intermittent failure or to add a Cloudflare data center in the same region as the origin.
An origin that is restarting. The origin is doing a graceful restart, and during the restart window, the origin’s port is closed for a few seconds. Cloudflare sees the closed port and returns 502. The fix is to add a small warmup window to the restart or to use a blue-green deploy where the new version is up before the old version is down.
A Cloudflare Worker that is failing. If you have a Cloudflare Worker in front of the origin, the Worker can return 502 if the Worker code throws. The fix is to check the Worker logs and to confirm the Worker is handling errors correctly.
How to set up a 502 alarm so you do not find out from a customer
The first time you hear about a 502 should not be from a customer. The setup is two things: a synthetic check and an alert.
Synthetic check. A cron job that runs every minute and curls the production URL. If the response is 502, the cron job exits non-zero. The cron job runs from a different network than the production origin (a separate host, a separate cloud account) to make sure the check is testing the full path.
Alert. A monitor on the synthetic check that pages the on-call when the check fails for 2 minutes in a row. Two minutes is enough to filter out transient edge failures but fast enough to catch a real 502 before customers notice.
The setup is 30 minutes of work. The 30 minutes pays for itself the first time a 502 stays up for 5 minutes and a customer notices before the alert fires. For a production deploy on RunxBuild, the synthetic check is a single cron job against the production URL, and the alert is a webhook to the on-call channel.
FAQ
Why does Cloudflare show a 502 when the origin is up?
The 502 is from Cloudflare’s edge, not from the origin. The most common causes are: a compression mismatch (origin sends gzipped with a stale Content-Length), a Cloudflare data center transient failure, or an Early Hints cache miss. Open https://www.cloudflarestatus.com/ and check the colo from your cdn-cgi/trace. If the colo is having an incident, the 502 will resolve when the incident does.
How do I tell if a 502 is from the origin or from Cloudflare?
Load the origin directly (curl -I https://origin.example.com). If the origin returns 502, the 502 is from the origin. If the origin returns 200, the 502 is from Cloudflare or a tunnel between Cloudflare and the origin. The same test works for the tunnel: cloudflared tunnel info <name> shows the connection status. A connected tunnel with an up origin and a Cloudflare 502 means the problem is at the Cloudflare edge.
Why does my Cloudflare Tunnel show “Unable to reach the origin service”?
The tunnel is connected to the Cloudflare network, but cloudflared cannot reach the application that the tunnel is configured to point at. The most common causes are: the application is not running on the host, the tunnel config points to a different port than the application is on, the tunnel config points to a different host than the application is on, or the SSL mode is “Full” but the origin’s certificate is self-signed. The fix is one of: restart the application, fix the tunnel config, point the tunnel at the right host, or change the SSL mode.
Does a 502 mean the origin is down?
Not always. A 502 from Cloudflare can come from the origin (most common), from Cloudflare’s edge (rare, often transient), or from a Cloudflare Tunnel (the case the docs bury). The diagnostic order is: check the Cloudflare status page, load the origin directly, check the tunnel status, and only then assume the origin is down. Restarting the origin is the right move only after the diagnostic confirms the origin is the cause.
Can a 502 be caused by a database?
Yes. The application is up, the application process is running, and the application’s health check fails because the database is unreachable. The 502 from Cloudflare in this case is correct — the application is unhealthy. The fix is the database, not the application. Check the database status, the connection string, and the database’s connection pool before restarting the application.
How do I tell if the 502 is from the WAF?
Test the same URL with the WAF disabled. In the Cloudflare dashboard, go to Security > WAF > Web Application Firewall, and toggle the WAF off for 30 seconds. Reload the URL. If the 502 is gone, the WAF is the cause. Re-enable the WAF and adjust the rule.
What is the fastest way to find the real cause of a Cloudflare 502?
The 30-second diagnostic: check cloudflarestatus.com, load the origin directly, check the tunnel status if you have one. The 90-second full checklist: status page, origin direct, tunnel status, origin logs, WAF rules. The first check that distinguishes the three cases (origin, Cloudflare, tunnel) is the one that tells you which fix to apply, and the 30 seconds to do the check are the most valuable 30 seconds in any 502 incident.