The site stopped answering. Not the backup I'd been fighting with all evening, the actual website. Every request came back with a 200 and a page that said "One moment, please..." and spun a spinner at me. The homepage did it. So did the API endpoint my own tooling uses to check the site is alive.
I run a server whose entire job is looking after client WordPress sites: checking they're up, keeping them backed up, applying updates. That evening one site had a stubborn backup problem, so I settled in and chased it. Build the archive. Watch it. Check the size. Try again. Read the plugin list. Upload a fix. Try again.
The site's security plugin had decided my server was attacking it, and on the evidence it was right. 589 requests to that one site in under twelve hours, and that's only the ones that got logged.
Where 589 requests come from
Almost all of them came from watching.
I had been polling a file size every ten seconds to see the archive grow, through two downloads that each took about twenty minutes. That alone is a couple of hundred requests spent watching a number go up. Add a health check after every attempt, a plugin list, a version check, a few deploys, and another look at the homepage every time something seemed off, and you get there without ever deciding to.
The challenge page is served by the WAF sitting in front of WordPress, which is why the homepage got it too. That also means there is nothing to fix on my end of the connection. The server has a standing, legitimate reason to talk to that site constantly, and now it has to be vouched for by a human and put on an allowlist before it can do the job it exists to do. Getting locked out is worse than never having had access in the first place: the tool with the best reason to be there is, in the logs, a threat.
The question was already answered on my own disk
The thing I kept going back to the site for was what is taking up all that space. The site measured 5.2 GB and I'd have guessed under two.
A 947 MB archive was already sitting on my own disk. tools/check_archives.py opens archive files directly, no site involved, and totting up the contents takes about four seconds. The answer was in there the whole time: 31 database dumps my own backup tool had left behind in the uploads folder. I went to the live site out of habit, not need.
What it cost, and what changed
Two finished fixes to services/deployer.py are sitting uncommitted in the working tree, tested against 285 green Python tests, because the only site that exercises them is the one I'm locked out of. The rest of that build-out waits on the same thing. The site should come out around 1.9 GB once the leaked dumps are gone, and I can't confirm it.
The rule that came out of it went straight into my working agreements, worded for a bot to obey: never make enough requests to get blocked. In practice it's two habits. Decide the request budget before you start poking, because automation has no sense of how often it's asking and you stop counting the moment you're absorbed in the problem. And ask whether the copy you already downloaded can answer the question, because the copy is free and the live system is somebody's business.
The second rule has a corollary I keep taped to this particular wound: do not probe to see whether a block has lifted. One request to the homepage answers it. Repeatedly checking is what caused it.
Measured September 30, 2026. The block is still on.