The standard rate-limiting pattern from the Laravel docs looks like this:
if ( RateLimiter :: tooManyAttempts ( 'send-message:' . $user -> id , $maxAttempts = 5 )) { return 'Too many attempts!' ; }
RateLimiter :: hit ( 'send-message:' . $user -> id );
// Send message...
Enter fullscreen mode
Exit fullscreen mode
It works fine. Right up until someone hits an endpoint capped at 5 requests per minute with 100 concurrent requests . Then all 100 get through.
I ran into this race condition while building rate limiting for captchaapi.eu , a PoW CAPTCHA API. Credit goes to @_newtonjob, who nailed it in 280 characters in a post on X :
Your Ratelimiting logic works until someone fires 100 concurrent requests on an endpoint that should be limited to 5 requests per minute.
The fix: Ensure you/your agents also check the incremented count returned by RateLimiter::hit() and that it doesn't exceed the max attempts.
Here's why it's a problem, the one-line fix, and what I took away from it.
Why is it a…