Four edge rules took main-site downtime from about 39 minutes a day to zero within the hour. Later the same day we found they were turning away real customer calendar feeds and search engines.
Finding the flood
The symptom was chronic blank error pages. To root-cause them we live-sampled 12 bursts and watched the origin’s on-box counters. None of the 12 moved. The origin was verified healthy, so scanner-bot floods were overwhelming the shared network front door upstream of it. New visitor connections were getting dropped at Cloudflare, and the 520 error flood was what visitors saw.
The fix was four Cloudflare edge rules:
- A skip rule so payment and SMS callbacks never hit the other rules.
- A block on
.phpand archive extensions. We extended the existing archive-extension rule and made the match case-insensitive, after finding the original was case-sensitive. - A block on scanner recon paths: environment files, git, WordPress admin and similar.
- A port block.
We validated the block rules against a week of production traffic before they went live.
The wrong turn on .php
We first staged .php as a challenge. Then we changed it to a flat block. Challenging 7.5M requests a week would add load at the exact connection bottleneck we were trying to relieve, so the staged rule would have made the problem it targeted worse.
Watching a number that thin
Downtime dropped to zero. The old uptime probe could never have caught a failure rate as thin as the one we now needed to watch for. So we built two things: a daily watch with alerting, and a guard that checks whether our own rules are blocking real visitors.
The allow rule that allowed nothing
When we checked the release, one allow rule turned out to be holding back only Cloudflare’s own managed filters. It did nothing about our new custom block rules. Real customer calendar feeds and search engines were getting turned away.
The ticket had already closed to staging with downtime at zero. That zero was true of the scanners and equally true of the real traffic we were cutting off, because a rule that blocks the wrong requests also produces zero error pages.
We fixed the allow rule, then confirmed the feeds were serving again while the scanner traffic was still blocked. We also filed a ticket for the WAF reference doc we were missing.
On Aug 26 one more real customer calendar feed turned out to be wrongly blocked, and we fixed that too.
Making the guard honest
The guard looks at blocked requests. Those carrying a referer from a customer’s wp-admin page could be real users caught by a rule. When we looked at them, they came from hosting IPs with a WordPress/6.4.3 user agent, probing paths that don’t exist on our side. That is scanners faking a referer, not real users. The same check gave the same answer on Sep 1 and again on Sep 28.
We also had to settle what counted in the metric. We applied measurement corrections so comparisons stayed honest, and we had to decide explicitly whether one media host belonged in the metric before running the final scan.
Where it stands
As of 2026-08-27, main-site error-minutes were down 83% (6.4/day against a 37.7 baseline) over 44.6 hours. By Sep 28, five weeks on, we checked live:
- Main-site error-minutes for Sep 21 to 27 were 23 in total, about 3.3 a day, down 91% from 37.7 a day. Yesterday had zero.
- Errors across all customer sites were 8 yesterday, against a pre-fix average of 6,459 a day.
- All four rules were still in place.
The errors that remain are slow-origin timeouts, and they belong to a separate ticket. We closed the flood ticket on that basis.
The rules hit the original goal of fewer error pages within the hour. But zero error pages is also exactly what rules rejecting real customers would have produced, so the count alone could never tell us which one we had. What told us was a standing check on what the rules block, and that is the check we kept running for five weeks.