- Laravel
- rate-limiting
- http
Prefix the by() keys when one limiter returns several limits
Three limits with the same by() key share one counter: the hour limit fills up at the minute's pace. A prefix per window keeps the counters apart.
1 min read
A limiter can return a list, which is how you get "60 a minute, 1,000 an hour, 10,000 a day" without writing a middleware. The catch is the cache key: it is built from the by() value, so three limits keyed by the same user id count in the same bucket.
RateLimiter::for('api', function (Request $request) {
$id = $request->user()?->id ?: $request->ip();
return [
Limit::perMinute(60)->by('minute:'.$id),
Limit::perHour(1000)->by('hour:'.$id),
Limit::perDay(10000)->by('day:'.$id),
];
});With the prefixes each window has its own counter and its own Retry-After. Without them the first request that hits any ceiling answers 429 for all three.
One more thing to know here: Limit::perMinutes(5, 100) takes the minutes first and the count second, the opposite of the other helpers.