Skip to content
OpenCloseEsc
Tips
  • Laravel
  • rate-limiting
  • security
  • http

Count only the responses you choose in a rate limit

Limit::after() decides after the response which requests count: only 404s for someone guessing ids, and never 422s, so a user fixing a form does not spend their own limit.

1 min read

A plain limit counts every request the same. Often the requests you want to stop are the failed ones.

RateLimiter::for('lookup', function (Request $request) {
    return Limit::perMinute(10)
        ->by($request->ip())
        ->after(fn (Response $response) => $response->status() === 404);
});

Someone walking through /orders/1, /orders/2, /orders/3 collects 404s and is blocked after ten. A real user who gets 200s is never counted.

The same closure turned around protects forms: return $response->status() !== 422, and a visitor correcting a validation error keeps their full limit for the request that finally succeeds.