<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Alex</title>
    <description>The latest articles on DEV Community by Alex (@errorrescue).</description>
    <link>https://dev.to/errorrescue</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4205017%2Fa4614533-3c13-401d-bcc3-8eeaa5896d2a.png</url>
      <title>DEV Community: Alex</title>
      <link>https://dev.to/errorrescue</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/errorrescue"/>
    <language>en</language>
    <item>
      <title>Cloudflare 520, 521, 522, 523, 524: How to Tell Them Apart and Fix Each From the Server Side</title>
      <dc:creator>Alex</dc:creator>
      <pubDate>Sat, 24 Oct 2026 15:44:14 +0000</pubDate>
      <link>https://dev.to/errorrescue/cloudflare-520-521-522-523-524-how-to-tell-them-apart-and-fix-each-from-the-server-side-3om2</link>
      <guid>https://dev.to/errorrescue/cloudflare-520-521-522-523-524-how-to-tell-them-apart-and-fix-each-from-the-server-side-3om2</guid>
      <description>&lt;p&gt;If you run sites behind Cloudflare long enough, you will meet the whole 52x family. They all look the same to a visitor: a Cloudflare-branded page saying something is wrong with the "host". But each code tells you something different about &lt;em&gt;where&lt;/em&gt; the conversation between Cloudflare and your origin server broke down.&lt;/p&gt;

&lt;p&gt;I've spent a lot of years fixing these on WordPress sites, VPSes and shared hosting, and the biggest time saver is simple: read the code carefully before touching anything. A 521 and a 524 have almost nothing in common, and fixing the wrong layer wastes hours.&lt;/p&gt;

&lt;p&gt;Here's how I approach them.&lt;/p&gt;

&lt;h2&gt;
  
  
  The quick comparison
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Code&lt;/th&gt;
&lt;th&gt;What Cloudflare saw&lt;/th&gt;
&lt;th&gt;First thing to check&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;520&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Connected, but got an empty, invalid or unexpected response&lt;/td&gt;
&lt;td&gt;Web server / PHP-FPM error logs, oversized headers&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;521&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Connection &lt;strong&gt;refused&lt;/strong&gt; by the origin&lt;/td&gt;
&lt;td&gt;Is Nginx/Apache running and listening on 80/443?&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;522&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;TCP connection &lt;strong&gt;timed out&lt;/strong&gt; (no answer at all)&lt;/td&gt;
&lt;td&gt;Firewall DROP rules, wrong origin IP, server overload&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;523&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Origin &lt;strong&gt;unreachable&lt;/strong&gt; (no route)&lt;/td&gt;
&lt;td&gt;DNS record value, stale AAAA record, host network&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;524&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Connected, but no HTTP response within ~100 seconds&lt;/td&gt;
&lt;td&gt;Slow PHP scripts or database queries&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;A useful mental model: 521, 522 and 523 are about &lt;strong&gt;getting a connection&lt;/strong&gt;. 520 and 524 are about &lt;strong&gt;what happens after&lt;/strong&gt; the connection is open.&lt;/p&gt;

&lt;h2&gt;
  
  
  The universal first step: talk to the origin directly
&lt;/h2&gt;

&lt;p&gt;Before changing anything in Cloudflare or on the server, take Cloudflare out of the picture. &lt;code&gt;curl --resolve&lt;/code&gt; lets you send a request for your real hostname straight to your origin IP, with the correct SNI and Host header:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Replace example.com and 203.0.113.10 with your domain and real origin IP&lt;/span&gt;
curl &lt;span class="nt"&gt;-svo&lt;/span&gt; /dev/null https://example.com/ &lt;span class="nt"&gt;--resolve&lt;/span&gt; example.com:443:203.0.113.10

&lt;span class="c"&gt;# Same over plain HTTP&lt;/span&gt;
curl &lt;span class="nt"&gt;-svo&lt;/span&gt; /dev/null http://example.com/ &lt;span class="nt"&gt;--resolve&lt;/span&gt; example.com:80:203.0.113.10
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Run it from a machine outside your server (your laptop is fine). What you see narrows things down fast:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;Connection refused&lt;/code&gt;&lt;/strong&gt; → you are looking at a 521 problem.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The command hangs, then times out&lt;/strong&gt; → firewall or network, think 522/523.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;Empty reply from server&lt;/code&gt;&lt;/strong&gt; or a reset mid-response → classic 520.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;It works but takes forever&lt;/strong&gt; → 524 territory.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;It works fine and fast&lt;/strong&gt; → the origin is healthy from the outside, so suspect something that only affects Cloudflare: a firewall blocking Cloudflare's IP ranges, a wrong IP in the Cloudflare DNS tab, or an SSL mode mismatch.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now let's go code by code.&lt;/p&gt;

&lt;h2&gt;
  
  
  520: the origin answered, but badly
&lt;/h2&gt;

&lt;p&gt;520 is Cloudflare's catch-all: the TCP connection worked, but what came back was empty, malformed or cut off. Most of the time the cause is a crashing backend.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Check the services and logs:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;systemctl status nginx       &lt;span class="c"&gt;# or apache2 / httpd&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;systemctl status php8.2-fpm  &lt;span class="c"&gt;# match your PHP version&lt;/span&gt;
&lt;span class="nb"&gt;sudo tail&lt;/span&gt; &lt;span class="nt"&gt;-n&lt;/span&gt; 50 /var/log/nginx/error.log
&lt;span class="nb"&gt;sudo grep&lt;/span&gt; &lt;span class="nt"&gt;-iE&lt;/span&gt; &lt;span class="s1"&gt;'segfault|exited on signal|max_children'&lt;/span&gt; /var/log/php&lt;span class="k"&gt;*&lt;/span&gt;&lt;span class="nt"&gt;-fpm&lt;/span&gt;.log
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;PHP-FPM workers dying with a segfault, or hitting &lt;code&gt;pm.max_children&lt;/code&gt;, are the usual suspects on WordPress sites.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Check header size.&lt;/strong&gt; Cloudflare rejects responses with very large headers, which often happens when a plugin sets huge cookies:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-s&lt;/span&gt; &lt;span class="nt"&gt;-D&lt;/span&gt; - &lt;span class="nt"&gt;-o&lt;/span&gt; /dev/null https://example.com/ &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--resolve&lt;/span&gt; example.com:443:203.0.113.10 | &lt;span class="nb"&gt;wc&lt;/span&gt; &lt;span class="nt"&gt;-c&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If the number is in the tens of kilobytes, find the cookie responsible. While you do, give Nginx bigger buffers so it doesn't choke:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight nginx"&gt;&lt;code&gt;&lt;span class="c1"&gt;# nginx.conf, inside http {}&lt;/span&gt;
&lt;span class="k"&gt;large_client_header_buffers&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt; &lt;span class="mi"&gt;32k&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;proxy_buffer_size&lt;/span&gt; &lt;span class="mi"&gt;16k&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;proxy_buffers&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt; &lt;span class="mi"&gt;16k&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A firewall that resets Cloudflare connections partway through can also produce 520, so the allowlist in the 521 section below is worth doing either way.&lt;/p&gt;

&lt;h2&gt;
  
  
  521: the origin refused the connection
&lt;/h2&gt;

&lt;p&gt;521 is the most straightforward. Cloudflare knocked and the server said no, either because nothing is listening or because something actively rejected it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Is the web server up and is the config valid?&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;systemctl status nginx
&lt;span class="nb"&gt;sudo &lt;/span&gt;nginx &lt;span class="nt"&gt;-t&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;sudo &lt;/span&gt;systemctl restart nginx   &lt;span class="c"&gt;# Apache: sudo apachectl configtest&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Is it listening on the public interface?&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;ss &lt;span class="nt"&gt;-tlnp&lt;/span&gt; | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-E&lt;/span&gt; &lt;span class="s1"&gt;':(80|443)\b'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You want to see &lt;code&gt;0.0.0.0:80&lt;/code&gt; / &lt;code&gt;0.0.0.0:443&lt;/code&gt; (or &lt;code&gt;[::]&lt;/code&gt;). If it's bound only to &lt;code&gt;127.0.0.1&lt;/code&gt;, Cloudflare can't reach it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Does the SSL mode match the origin?&lt;/strong&gt; With Cloudflare SSL set to &lt;em&gt;Full&lt;/em&gt; or &lt;em&gt;Full (strict)&lt;/em&gt;, Cloudflare connects on port 443. If your origin only serves HTTP, every request gets refused:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;nginx &lt;span class="nt"&gt;-T&lt;/span&gt; | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-E&lt;/span&gt; &lt;span class="s1"&gt;'listen .*443'&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;apachectl &lt;span class="nt"&gt;-S&lt;/span&gt; | &lt;span class="nb"&gt;grep &lt;/span&gt;443
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Allow Cloudflare's IP ranges.&lt;/strong&gt; All your traffic arrives from a small set of Cloudflare IPs, which makes them easy targets for Fail2ban, CSF/LFD or rate limits. Allowlist the official ranges:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="k"&gt;for &lt;/span&gt;ip &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="si"&gt;$(&lt;/span&gt;curl &lt;span class="nt"&gt;-s&lt;/span&gt; https://www.cloudflare.com/ips-v4&lt;span class="si"&gt;)&lt;/span&gt; &lt;span class="si"&gt;$(&lt;/span&gt;curl &lt;span class="nt"&gt;-s&lt;/span&gt; https://www.cloudflare.com/ips-v6&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;do
  &lt;/span&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;ufw allow proto tcp from &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$ip&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; to any port 80,443 comment &lt;span class="s1"&gt;'Cloudflare'&lt;/span&gt;
&lt;span class="k"&gt;done
&lt;/span&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;ufw reload

&lt;span class="c"&gt;# Check Fail2ban hasn't banned any of them&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;fail2ban-client status
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;On CSF, add each range to &lt;code&gt;/etc/csf/csf.allow&lt;/code&gt; and run &lt;code&gt;sudo csf -r&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  522: the connection timed out
&lt;/h2&gt;

&lt;p&gt;The difference from 521 is subtle but important: with 522 nobody said no. Packets just disappeared. That points to a firewall that &lt;strong&gt;drops&lt;/strong&gt; instead of rejecting, the wrong IP, or a server too busy to accept connections.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Confirm Cloudflare is pointing at the right server.&lt;/strong&gt; After a migration, a stale A record is the number one cause I see:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# On the server: its real public IPv4&lt;/span&gt;
curl &lt;span class="nt"&gt;-4&lt;/span&gt; &lt;span class="nt"&gt;-s&lt;/span&gt; https://ifconfig.me

&lt;span class="c"&gt;# From outside: does that IP answer on 443 at all?&lt;/span&gt;
nc &lt;span class="nt"&gt;-vz&lt;/span&gt; &lt;span class="nt"&gt;-w&lt;/span&gt; 5 203.0.113.10 443
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Compare that IP with the A record in the Cloudflare DNS tab. Note that &lt;code&gt;dig example.com&lt;/code&gt; will show Cloudflare's IPs for proxied records, which is expected and tells you nothing about the origin.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Look for DROP rules and connection limits:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;iptables &lt;span class="nt"&gt;-L&lt;/span&gt; INPUT &lt;span class="nt"&gt;-n&lt;/span&gt; &lt;span class="nt"&gt;--line-numbers&lt;/span&gt; | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-E&lt;/span&gt; &lt;span class="s1"&gt;'DROP|REJECT|connlimit'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Check whether the server is simply overloaded:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;uptime
&lt;/span&gt;free &lt;span class="nt"&gt;-m&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;ss &lt;span class="nt"&gt;-s&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;ss &lt;span class="nt"&gt;-tn&lt;/span&gt; state syn-recv | &lt;span class="nb"&gt;wc&lt;/span&gt; &lt;span class="nt"&gt;-l&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A big pile of connections stuck in &lt;code&gt;SYN-RECV&lt;/code&gt; means the server isn't keeping up. On Nginx, make sure workers aren't the bottleneck, and keep keep-alive on, because Cloudflare reuses connections:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight nginx"&gt;&lt;code&gt;&lt;span class="k"&gt;worker_processes&lt;/span&gt; &lt;span class="s"&gt;auto&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;events&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="kn"&gt;worker_connections&lt;/span&gt; &lt;span class="mi"&gt;4096&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;http&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kn"&gt;keepalive_timeout&lt;/span&gt; &lt;span class="s"&gt;75s&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  523: the origin is unreachable
&lt;/h2&gt;

&lt;p&gt;523 means Cloudflare couldn't even find a route to your origin. It's almost always DNS or the hosting provider's network, rarely your web server config.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Check both IPv4 and IPv6.&lt;/strong&gt; A forgotten AAAA record is a sneaky cause: Cloudflare may try IPv6 and fail, while everything looks fine over IPv4.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-4&lt;/span&gt; &lt;span class="nt"&gt;-s&lt;/span&gt; https://ifconfig.me
curl &lt;span class="nt"&gt;-6&lt;/span&gt; &lt;span class="nt"&gt;-s&lt;/span&gt; https://ifconfig.me   &lt;span class="c"&gt;# if this fails, remove the AAAA record in Cloudflare&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Trace the route from outside:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;mtr &lt;span class="nt"&gt;-rwc&lt;/span&gt; 50 203.0.113.10
&lt;span class="c"&gt;# or&lt;/span&gt;
traceroute 203.0.113.10
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If the trace dies before reaching your server, the problem is upstream. Save the output and send it to your host; it's exactly what their network team will ask for.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Make sure the server's own network is up:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ip &lt;span class="nt"&gt;-br&lt;/span&gt; addr
ip route show default
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;No default route after a reboot or a netplan change will produce 523 just as reliably as a dead data center.&lt;/p&gt;

&lt;h2&gt;
  
  
  524: the origin was too slow
&lt;/h2&gt;

&lt;p&gt;With 524, everything connected fine, but the origin didn't send a response before Cloudflare's timeout (100 seconds on the Free, Pro and Business plans). You can't raise that limit by tuning your server; you have to make the request faster or move it out of the proxied path.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Measure the slow URL directly:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-so&lt;/span&gt; /dev/null &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-w&lt;/span&gt; &lt;span class="s1"&gt;'connect=%{time_connect}s ttfb=%{time_starttransfer}s total=%{time_total}s\n'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  https://example.com/slow-page/ &lt;span class="nt"&gt;--resolve&lt;/span&gt; example.com:443:203.0.113.10
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A &lt;code&gt;ttfb&lt;/code&gt; near 100 seconds is your answer.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Find what's slow.&lt;/strong&gt; Turn on the PHP-FPM slow log and the MySQL slow query log:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ini"&gt;&lt;code&gt;&lt;span class="c"&gt;; /etc/php/8.2/fpm/pool.d/www.conf
&lt;/span&gt;&lt;span class="py"&gt;request_slowlog_timeout&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;10s&lt;/span&gt;
&lt;span class="py"&gt;slowlog&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;/var/log/php-fpm-slow.log&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SET&lt;/span&gt; &lt;span class="k"&gt;GLOBAL&lt;/span&gt; &lt;span class="n"&gt;slow_query_log&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;SET&lt;/span&gt; &lt;span class="k"&gt;GLOBAL&lt;/span&gt; &lt;span class="n"&gt;long_query_time&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The slowlog gives you a PHP stack trace for every request over 10 seconds, which usually points straight at the plugin or query to blame.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Move long jobs out of the request.&lt;/strong&gt; Imports, exports, backups and reports shouldn't run inside a web request. On WordPress, run cron from the system instead of on page load:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="c1"&gt;// wp-config.php&lt;/span&gt;
&lt;span class="nb"&gt;define&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'DISABLE_WP_CRON'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# crontab -e&lt;/span&gt;
&lt;span class="k"&gt;*&lt;/span&gt;/5 &lt;span class="k"&gt;*&lt;/span&gt; &lt;span class="k"&gt;*&lt;/span&gt; &lt;span class="k"&gt;*&lt;/span&gt; &lt;span class="k"&gt;*&lt;/span&gt; &lt;span class="nb"&gt;cd&lt;/span&gt; /var/www/html &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; wp cron event run &lt;span class="nt"&gt;--due-now&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt;/dev/null 2&amp;gt;&amp;amp;1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For admin tools that genuinely need minutes, put them on a subdomain that isn't proxied (grey cloud) in Cloudflare.&lt;/p&gt;

&lt;h2&gt;
  
  
  A short checklist to keep around
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Read the exact code. Refused (521), timed out (522), unreachable (523), bad response (520) and slow response (524) are different problems.&lt;/li&gt;
&lt;li&gt;Run &lt;code&gt;curl --resolve&lt;/code&gt; against the origin from outside before changing anything.&lt;/li&gt;
&lt;li&gt;Allowlist Cloudflare's IP ranges in every firewall layer you have.&lt;/li&gt;
&lt;li&gt;Verify the origin IP (and any AAAA record) in the Cloudflare DNS tab.&lt;/li&gt;
&lt;li&gt;Check logs before restarting services. A restart hides the evidence.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Full step-by-step guides
&lt;/h2&gt;

&lt;p&gt;Each of these codes has more causes and edge cases than fit in one post. I keep detailed, regularly updated guides for each on ErrorRescue:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://errorrescue.com/error-520/" rel="noopener noreferrer"&gt;Cloudflare Error 520: Web Server Returned an Unknown Error&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://errorrescue.com/error-521-web-server-is-down/" rel="noopener noreferrer"&gt;Cloudflare Error 521: Web Server Is Down&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://errorrescue.com/error-522-connection-timed-out/" rel="noopener noreferrer"&gt;Cloudflare Error 522: Connection Timed Out&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://errorrescue.com/error-523-origin-is-unreachable/" rel="noopener noreferrer"&gt;Cloudflare Error 523: Origin Is Unreachable&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://errorrescue.com/error-524-timeout-occurred-causes-fix-guide/" rel="noopener noreferrer"&gt;Cloudflare Error 524: A Timeout Occurred&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you've hit a 52x case that didn't fit any of these patterns, I'd like to hear about it in the comments.&lt;/p&gt;

</description>
      <category>cloudflare</category>
      <category>devops</category>
      <category>webdev</category>
      <category>linux</category>
    </item>
  </channel>
</rss>
