Built and run by one person.

Why does my per-IP rate limit do nothing against this attacker?

Because no single address is doing anything wrong. An attacker no longer needs one fast machine. They rent a pool of thousands of home-internet addresses and send one request from each, so nothing ever approaches a per-address limit. Set that limit to two a minute and nothing changes.

The obvious lever is the useless one, and the next one is worse. A global limit low enough to stop the pool also stops your real users, because the pool is built to look like ordinary traffic one request at a time. And because these are real households, a block lands on a person who did nothing.

Stop reasoning about addresses and start reasoning about the work. Two things hold, and neither reads the address:

Read the signal as distinct callers failing together, not volume from any one of them. Many addresses failing at once means either you are broken or a pool is probing. And notice that "one request per address, hundreds of addresses, the same client fingerprint" is itself a signature: the addresses rotate, the client usually does not.

Measure before you build. On one of our own surfaces a per-address burst limit was proposed for exactly this problem and, replayed against the real traffic, it would have refused nobody in the pool and several real users. The distinct-callers signal has its own false positive worth knowing: one person iterating a query through a rotating proxy looks like a distributed probe until you read the payloads and find twelve variants of the same question. Read the payload shapes before you believe an address count.

Treat a block as a last resort, keep it short, and expect the pool to move on the next day whatever you do.

Related: whether your edge rate limit enforces the number you configured, rate limiting and getting the real client IP, and the perimeter section of the checklist.

Building something like this? How I work covers the rates, the availability and what I take on.

← All Agents FAQ