Separate the edge and origin with the same request
When a site behind Cloudflare is slow or returns 520, 521, 522, 524, 525, or 526, changing DNS, WAF, cache, Tunnel, and the origin web server together destroys the first useful failure boundary. Compare the edge response received by the user with the response produced by the origin under the same URL, time, and Host conditions.
Record the full URL, timestamp and timezone, HTTP status, and Cf-Ray as one incident key. Cf-Ray connects a request across Cloudflare and origin logs; it does not identify the cause by itself. A cache value such as HIT, MISS, or DYNAMIC also does not prove success or failure on its own.
A real 504 investigation: notification time was not failure time
On 2026-10-22, we investigated this site’s Search Console server-error notification. The current path is Cloudflare Tunnel → Nginx → PHP-FPM → WordPress/MariaDB. Comparing origin logs, Google’s stored inspection result, and current requests separated different observations. Times below are UTC; add nine hours for Korea Standard Time.
# Observed origin records; IPs and other identifiers omitted
2026-10-16T17:17:40Z GET /privacy-policy/ status=504
upstream timed out ... while reading response header from upstream
| UTC time | Available observation | Limit of interpretation |
|---|---|---|
| Oct 16, 17:17:40 | /privacy-policy/ origin access log: 504; error log: upstream response-header timeout | Nginx failed while waiting for FastCGI response headers. The slow PHP function or database request is unknown |
| Oct 20, 01:36:41 | Stored Google inspection of the same URL: successful fetch, indexed | A successful later crawl; not a current live test |
| Oct 22, 07:56:26 | Search Console server-error email received | Searching only around the email time would miss the recorded failure |
| Oct 22 investigation | All 130 unique current sitemap URLs returned HTTP 200 | Establishes current reachability, not the absence of historical failures |
Among 102,944 retained origin requests from September 12 through October 22, this was the only origin 5xx. However, the complete article inspection also found stored Google 5xx records for three other URLs; all three currently returned 200. We did not label those Cloudflare failures merely because no matching origin error was retained. Without the historical edge response and Ray ID, the failing layer for those three remains unknown.
The origin User-Agent said Googlebot, but the origin connection address behind the tunnel could not verify Google’s actual client IP. A request with a Googlebot User-Agent does not replace a real Google request. The URL Inspection API returns Google’s stored state, so a current curl 200 can coexist with a historical Google 5xx.
Established by this case: one historical FastCGI timeout, a later successful stored crawl, and current reachability. We cannot attribute it to a plugin, insufficient memory, or a PHP vulnerability, or claim today’s service restarts repaired that incident. A recurrence needs matching timestamps, Ray IDs, origin durations, and PHP slow logs to narrow the cause further.
A normal baseline captured from the Nole IT stack
The following baseline was captured on 2026-08-08 from this site’s Synology NAS, Docker WordPress, MariaDB, and Cloudflare Tunnel/DNS path. Identifying values were removed. This is not a deliberately reproduced outage. It preserves the layers that answer during normal operation so a later incident can be compared against the same boundary.
# 2026-08-08, identifying values redacted
EDGE HTTP 200 | server=cloudflare | cf-cache-status=DYNAMIC | cf-ray=present
ORIGIN HTTP 200 | server=Apache/2.4.x (Debian)
DNS two proxied A answers
TLS wildcard SAN matched | certificate valid at test time
Both the edge and origin returned HTTP 200 in this baseline, so the delivery path from Cloudflare to the origin was working at that time. cf-cache-status=DYNAMIC means this WordPress response was not a normal cache hit; it is not evidence of latency. During the next incident, the same commands must show whether only the origin is fast or both paths are slow.
A separate healthy observation after the Oracle move
At 11:21 UTC on September 13, 2026, read-only checks returned 200 for both the public HTTPS home and the current Oracle origin HTTP home with the same Host over the management connection. These were separate requests, not a load or latency comparison or reproduced 5xx recovery. The August 8 NAS results above remain historical observations.
Oracle migration verification record
Values to capture before a change
| Layer | Values to capture | Decision rule |
|---|---|---|
| Client and edge | URL, time, status, Cf-Ray, cf-error-type |
A response with Cf-Ray can be traced through Cloudflare |
| Cache | cf-cache-status, response time, retry result |
Interpret cache state together with origin contact |
| Origin | Direct response with the same Host, web log, application log | Compare edge and origin status and timing |
| TLS | SNI, certificate SAN, expiry, origin TLS log | For 525 and 526, repair the certificate path before retrying |
| Security rules | Security Events action, rule ID, request time | Consider the narrowest WAF exception only when an event exists |
curl -sS -D edge.headers -o /dev/null https://example.com/
curl -sS -D origin.headers -o /dev/null -H 'Host: example.com' http://<ORIGIN_IP>:<PORT>/
grep -Ei '^(HTTP/|server:|cf-ray:|cf-cache-status:|cf-error-type:|cf-error-origin:)' edge.headers
Run a direct-origin request only from a management network or an authenticated diagnostic path. Do not disable the public DNS proxy or expose the origin address for this test. A Tunnel deployment may not permit public origin-IP bypass, so send the same Host header from the origin LAN or Docker host instead.
Where each 5xx code points first
| Status | Scope identified by Cloudflare | First place to inspect |
|---|---|---|
520 |
An empty, unknown, or unexpected origin response | PHP/web-server crash, oversized headers, early close |
521 |
The origin web server refused the connection or is down | Listen port, service state, blocked Cloudflare addresses |
522 |
TCP connection timeout between Cloudflare and origin | Firewall, routing, origin load, connection count |
524 |
Timeout while waiting after the origin connection | Slow request, database lock, upstream processing time |
525 |
TLS handshake failed between Cloudflare and origin | SNI, cipher, origin certificate, TLS error log |
526 |
Origin certificate validation failed | Certificate chain, hostname, expiry, SSL mode |
Do not decide from the error page alone whether 500, 502, 503, or 504 was generated by Cloudflare or passed through from the origin. Compare cf-error-type, origin logs, and edge/origin status in Error Analytics. Current Cloudflare-generated error responses can provide structured data when requested with Accept: application/json, but that behavior does not rewrite an origin-generated 5xx body.
curl -sS --compressed -H 'Accept: application/json' https://example.com/cdn-cgi/error/522
curl -sS --compressed -D - -o /dev/null -H 'Accept: application/json' https://example.com/cdn-cgi/error/521
These paths demonstrate error-response formats. A 522 response from /cdn-cgi/error/522 does not prove that your origin timed out. Diagnose the original URL that actually failed for a user. Store demonstration responses, healthy baselines, and real incident logs as different types of evidence.
The HTTP origin comparison applies when the Tunnel connects to that HTTP service. If the origin itself uses HTTPS, do not downgrade it for comparison: keep the original hostname and SNI in an HTTPS request. A valid edge certificate does not establish that origin certificate validation also succeeded.
Align the logs in chronological order
- Reproduce one failing request and record its URL, UTC or explicitly named local time, status, and
Cf-Ray. Do not mix several refresh attempts. - Check Cloudflare Security Events for a blocking action at the same time. If there is no event, stop treating WAF disablement as the next step.
- Where the plan and log product allow it, search for
Cf-Rayor Ray ID and compare edge status with origin status. Log access differs by plan. - Find the same time and
Cf-Rayin origin access and error logs. If the request never reached the origin log, inspect Tunnel, firewall, and TLS before editing the application. - If the origin logged
HTTP 200while the edge failed, narrow oversized headers, early close, and Transform/Worker rules. If the origin also logged 5xx, prioritize the application and database logs.
A Logpush OriginResponseStatus value of 0 is not always an origin failure. When CacheStatus in the same record is hit or revalidated, Cloudflare may have served a normal cache path without contacting the origin. When CacheStatus is miss or expired and OriginResponseStatus is 0, there is evidence that the origin connection ended before valid HTTP response headers arrived.
Change one layer at a time
- Only when Security Events contains the actual rule ID should a Skip rule be narrowed to the affected path, method, and source conditions. Avoid disabling the entire WAF even as a comparison test.
- For
521or522, restore the origin listener and Cloudflare/Tunnel connection first. Cache purge cannot repair a failed TCP connection. - For
524, measure origin processing time, database locks, and external API waits before increasing a timeout. A larger value can hide the slow path. - For
525or526, do not leave the zone in Flexible mode. Repair the origin certificate, SNI, chain, and Cloudflare SSL mode so they agree. - When only one path fails, compare one Worker, Redirect Rule, or Transform Rule at a time and record its original value and priority.
Verification and rollback
After a change, repeat both the edge and direct-origin requests with the original URL and request conditions. Do not stop when the status changes to HTTP 200; also confirm response time, Cf-Ray traceability, and arrival in the origin log. Retain one normal request and one formerly failing request to reduce cache-only success.
Save every rule expression, action, and priority before editing. Keep origin configuration in a file backup or deployable revision. If the fault moves to another layer or valid traffic becomes blocked, roll back only the last change and compare it with the baseline again.
Related guides
Official references
- Cloudflare 5xx errors – investigation scope for edge and origin error codes
- Gathering information for troubleshooting sites – direct-origin comparison and Cf-Ray log correlation
- Cloudflare error diagnostic headers – interpreting cf-error-type and cf-error-origin
- Cloudflare Error 520 – reading CacheStatus with OriginResponseStatus