Rate Limit not limitting

I have a simple worker that reads an API Key from D1 and shall use the rate limitter to apply limits to it. I've configured a very small limit in my config to test it:
[[unsafe.bindings]]
name = "RPC_LIMITER"
type = "ratelimit"
namespace_id = "1"
simple = { limit = 1, period = 60 }
[[unsafe.bindings]]
name = "RPC_LIMITER"
type = "ratelimit"
namespace_id = "1"
simple = { limit = 1, period = 60 }
and I wanted to test the limit, it was not applied. Even calling it with a hard coded key does not limit it in my tests:
const limit = await env.RPC_LIMITER.limit({ key: "apiKey.userId" })
const { success } = limit
if (!success) {
return new Response(`429 Failure – rate limit exceeded for ${apiKey.userId}`, { status: 429 })
}
const limit = await env.RPC_LIMITER.limit({ key: "apiKey.userId" })
const { success } = limit
if (!success) {
return new Response(`429 Failure – rate limit exceeded for ${apiKey.userId}`, { status: 429 })
}
Am I missing something? It seems like the limitter is not incrementing. Thanks a lot, in advance, for any help!
3 Replies
favo
favoOP5mo ago
When is eventually? Should it not apply after a few seconds? With the above example, I set it to 1 request per minute. Running with a delay of a few seconds (5 or 30) is what I expected to be incremented at least. reduced to the smallest testable version:
export default {
async fetch(request, env): Promise<Response> {
const { success } = await env.RPC_LIMITER.limit({ key: "test" })
if (!success) {
return new Response(`429 Failure – rate limit exceeded`, { status: 429 })
}

return new Response('success')
}
}
export default {
async fetch(request, env): Promise<Response> {
const { success } = await env.RPC_LIMITER.limit({ key: "test" })
if (!success) {
return new Response(`429 Failure – rate limit exceeded`, { status: 429 })
}

return new Response('success')
}
}
(wrangler 3.63.2) calling:
curl https://WORKER && sleep 10 && curl https://WORKER
curl https://WORKER && sleep 10 && curl https://WORKER
will always return success – even if the second call after 10 second is above the rate limit of 1 request per minute. 10 seconds to sync the storage is something I expect. Am I doing something wrong or is there an issue with the limitter? if "eventually consistent" is outside of the configurable period and I can not limit someone to 1req within a 60s timeframe, whats the purpose of it at all? I very much would love to use the new service instead of relying on my own implementation. Is there someone who can help?
Sam
Sam3w ago
Did you find a solution @favo ?
Peter
Peter3w ago
I agree with what Leo says here. To expand on that, the rate limiting in Workers is not likely going to work very well for really small numbers of requests. To ensure that your Workers are fast (and bills small 🙂 ) the counters are updated in the background. There are many servers in a Colo and there can be several POPs in an MCP to spread your requests over. If you are unlucky you may even find your requests are split between POPs. All of this is to say that the rate limit system will not know about the most recent state on all servers. The key thing is not the 10 seconds but the vast number of servers and the odds of your 2nd curl request being routed to the same server is pretty unlikely. If you need to rate limit on really small numbers of requests in short time periods then I recommend using another Workers product. When using your browser, it will likely keep the connection open which will increase very significantly the chance that a 2nd and subsequent request reaches the same worker with up to date state.
Want results from more Discord servers?
Add your server