The limit that limits nothing · 7 of 20

A read-then-write counter on an eventually consistent store is not a rate limit

Hit in our code
Check it
# against YOUR staging site, never someone else'sseq 1 50 | xargs -P 50 -I{} curl -s -o /dev/null -w "%{http_code}\n" -X POST https://staging.yoursite.com/api/subscribe \  -H "Content-Type: application/json" -H "Origin: https://staging.yoursite.com" \  -d '{"email":"x{}@example.com","website":""}' | sort | uniq -c
Free, no call

Get every Fix AI Slop Code episode

The code it wrote, the code it should have written and a check, for every episode

Free, straight to your inbox. No call, no pitch

Watch the video

Watch the episode

The same idea in a short video. It plays here, and nothing loads until you press play

What is going on

Cloudflare KV, and most edge key-value stores, take up to about 60 seconds to propagate a write. A limiter that reads the count, compares, then writes the count back has a race the width of that window. Two hundred requests in the same second all read zero and all pass. The green "rate limited" badge is true only for a polite visitor.

Where it bit

Our own email capture shipped with this exact limiter: five per hour, as get, compare, put on KV. Same shape as the rate-limit-on-the-button mistake, one layer down: the limit lived on the server and still did not hold. It now sits behind an atomic edge limit, with the KV count kept only as a backstop.

The practice

Limits need an atomic counter: a Durable Object, Redis INCR with expiry, or the platform's own rate-limiting rule at the edge. Coarse KV limits are fine as a second layer, never the only one.

Free, no call

Get this check as a script you can run tonight

Free, straight to your inbox. No call, no pitch

What to do with this

If this check came back with more than you expected, that is worth a conversation

Book a free 30-minute call