Cloudflare 522 means the packets went nowhere
A 522 is not a status code your server sent. Your server sent nothing, which is the entire message. Cloudflare tried to open a connection to it, waited, gave up, and generated its own error page carrying a number that identifies which step failed.
That is the useful property of the 52x family and the reason it is worth learning: unlike a generic 502, each number names a specific point in the sequence.
| Code | Where it stopped |
|---|---|
| 520 | The origin answered with something Cloudflare could not interpret |
| 521 | The origin actively refused the connection |
| 522 | The connection attempt got no answer at all, and timed out |
| 523 | Cloudflare could not route to the origin address |
| 524 | Connected fine, sent the request, no response in time |
| 525, 526 | The TLS handshake with the origin failed, or its certificate was rejected |
522 against 524, which is the distinction that matters
These two get treated as the same problem and they are opposites.
524 means the connection succeeded. TCP completed, TLS completed, the request was delivered, and the origin did not produce a response within Cloudflare's limit, which is 100 seconds on the standard plans (Cloudflare, "Troubleshooting Cloudflare 5XX errors", consulted 1 August 2026). Your server is alive and thinking. The problem is a slow query, a stuck external call, or a process pool with nothing free. This is an application problem and it is yours.
522 means the connection never happened. Cloudflare sent a connection request and received nothing back, not even a refusal. Your application is not involved, because nothing ever reached it. This is a network or a firewall problem, and it is frequently not yours.
So the first thing a 522 tells you is where not to look. There will be nothing in the application log, nothing in the access log, and nothing in the error log, because from the origin's point of view no request occurred. People spend an hour reading logs that were never going to contain anything.
Nothing back is different from a refusal
A machine that is up but has nothing listening on the port sends a refusal immediately, and Cloudflare reports that as 521. A packet that is silently discarded produces no answer at all, and the caller waits for a timeout, which is 522.
Silence is almost always deliberate. Operating system firewalls, cloud security groups and intrusion-prevention tools default to dropping rather than refusing, on the reasoning that a refusal confirms the address exists. So a 522 is, more often than any other single cause, something in the path deciding not to talk to Cloudflare.
The same distinction, from the point of view of a browser rather than a proxy, is why one failure returns instantly and the other hangs: a refusal eliminates far more possibilities than a timeout.
The five causes, in the order to check them
The firewall stopped allowing Cloudflare. Either the origin only accepts connections from Cloudflare's published ranges and those ranges changed, or an automated tool banned one of them. Rate limiters and intrusion-prevention daemons are the usual culprit: they see thousands of requests from a handful of addresses, which is exactly what a reverse proxy looks like, and ban them.
sudo fail2ban-client status
sudo iptables -L -n --line-numbers | head -40
curl -s https://www.cloudflare.com/ips-v4 | head
An address from that last list appearing in a ban table is your answer, and the fix is to whitelist the ranges permanently rather than unban once.
The origin address in the DNS record is stale. Cloudflare connects to whatever address the record holds. If the site moved and the record was not updated, Cloudflare is faithfully connecting to a machine that belongs to somebody else now, and getting nothing.
The server ran out of capacity to accept connections. Not out of memory, out of accept queue. A machine under heavy load can stop completing handshakes while still appearing to be up, and the symptom from outside is precisely a timeout.
The host's own protection intervened. Shared hosts run their own filtering above your account, invisible to you, and it can decide that the traffic pattern from a proxy is abusive.
The machine is genuinely gone. Rebooting, migrated, suspended for non-payment. Rare, and worth ruling out before spending an hour on firewalls.
Proving it, by going around the proxy
Connect to the origin directly while presenting the real hostname, so that virtual hosting behaves normally:
curl -sSI --resolve example.com:443:203.0.113.10 https://example.com/ --max-time 15
Three possible outcomes and each one is conclusive. A response means the origin is fine and something between it and Cloudflare is the problem, which is the firewall path above. A refusal means nothing is listening, and you should be seeing 521 rather than 522. A timeout from your machine as well means the origin is dropping packets from everybody, not only from Cloudflare, which points at the host rather than at a Cloudflare-specific rule.
Do that test from a network that is not the client's office, because an office address may be treated differently from the rest of the internet by the same tooling that is blocking the proxy.
What this means for what you record
A monitoring check that only stores "5xx" or "error" throws away the number, and the number is the diagnosis. A 522 and a 524 arriving from the same site an hour apart describe two unrelated faults with two different owners.
Record the exact code and record the body, because on a Cloudflare error page the useful detail, including which data centre served it and the ray identifier, is in the page rather than in the status line. That identifier is what a support conversation needs, and it exists only in the response you discarded.
And note that all of this sits on top of the ordinary case where a proxy reports a failure of the thing behind it, which has the same shape whether the proxy is Cloudflare or your own nginx: the relay is telling you about somebody else's silence.