Jun 2026 · 6 min read

I Built a Wall to Block Bots and the First Thing It Blocked Was Me

This morning I shipped what I was sure was the smartest thing I'd built all week.

By lunch it had taken down my own dashboard.

Let me back up.

The actual problem

If you read my last post you know the deal: most of the traffic hitting my landing pages isn't human. Last time I checked it was 80% bots.

I already had a Cloudflare Worker filtering them out. Worked fine.

Except there was a catch I never thought about.

Every bot request still hit the Worker.

Cloudflare's free plan gives you 100,000 Worker requests a day. And when bots are hammering you by the thousands, those fake requests burn your quota exactly like real ones do.

So I was basically paying — in quota — for the privilege of telling bots no.

That's backwards.

Galaxy brain meme
My bot defense evolution: block them in the Worker → realize the Worker IS the cost → block them before the Worker even wakes up

The fix that felt genius

Cloudflare has a thing called the WAF — the firewall that runs at the edge, before your Worker. Block something there and it never touches your Worker quota. Free.

So I moved all the bot rules up into the zone-level WAF.

One of those rules was this:

# Block path scanners. No real landing-page URL contains a dot.
http.request.uri.path contains "."
  and http.request.uri.path ne "/favicon.ico"
  and http.request.uri.path ne "/robots.txt"

The logic is clean. Scanners probe for files. /wp-login.php, /.env, /backup.zip. Every one of those has a dot in it. A real landing-page URL is just /something — no dot, ever. So if the path has a dot, it's a scanner. Block it.

For a landing page, this rule is perfect.

Then I made it auto-apply to every domain in my account.

Clown makeup meme
Me confidently rolling out "block any path with a dot" to every single domain I own

Five minutes later

I open my dashboard.

No CSS.

Just naked HTML. White background, Times New Roman, buttons stacked on top of each other like it's 1996.

I stared at it thinking the server died. Restarted Flask. Nothing. Cleared the cache. Nothing.

Then it hit me.

Monkey neuron activation meme
The exact moment I remembered my dashboard loads /static/dashboard.css

/static/dashboard.css

That has a dot in it.

My own rule — the one I wrote to block scanners probing for files — looked at my dashboard politely asking for its own stylesheet and went: "path contains a dot, that's a scanner, blocked."

The dashboard wasn't broken. My firewall was working flawlessly. On me.

Drake Hotline Bling meme
Blocking actual scanners hammering my LPs / Blocking my own CSS file

Why it only hit the dashboard

Here's the part that's almost poetic.

The rule is genuinely correct for a landing page. LP URLs never have dots. A scanner asking for /xmlrpc.php on an LP is 100% hostile, every time.

But a dashboard isn't a landing page. It's an app. Apps load assets — .css, .js, .png, fonts. Dots everywhere. And every single one of them is legitimate.

Same rule. Opposite meaning. It depends entirely on what's sitting behind the domain.

I'd written a rule for one kind of site and bulk-applied it to a completely different kind.

The fix

Two parts.

First, stop the bleeding: strip the WAF rules off the two domains that serve the dashboard. Thirty seconds through the API. The CSS came back instantly.

Undertaker sitting up from coffin meme
My dashboard the second I deleted one WAF rule

Second, the actual cleanup: the dashboard had no business living on a domain that also runs landing-page defenses. So I moved it off entirely — onto its own subdomain on my business domain, far away from any LP bot rule.

Now the LP zones keep their wall. The dashboard lives somewhere those rules never run.

The bigger realization

The rule was never wrong. My blast radius was.

"Block anything with a dot" is genius for a landing page and suicide for an app — and I applied it to both, because I was thinking about traffic instead of thinking about what each domain actually does.

A defense that can't tell the difference between your enemy and your own infrastructure will eventually catch your own infrastructure.

This is fine meme
Me mid-incident, explaining that technically the firewall is working perfectly

Bot protection that blocks bots: good.

Bot protection that blocks your own CSS: still, technically, blocking something.

Funny how that works.