RateLimit
The RateLimit package protects individual routes from repeated requests from the same client.
Use it when you want a route-level throttle such as "60 requests per minute" without building your own counters.
What the package provides
The package combines three pieces:
Route::rateLimit($limit, $interval)to declare a throttle on a routeRateLimitMiddlewareto enforce that throttle during the framework middleware stageRateLimiterFactoryandRateLimiterto resolve the configured storage adapter
The built-in adapters are:
fileredis
Basic example
Router::get('/api/posts', 'PostController', 'index')
->rateLimit(60, 60);
This means the matched route allows up to 60 hits per 60-second window for the same request method, route pattern, and client IP.
How requests are grouped
The limiter builds one key from:
- the HTTP method
- the route pattern
- the client IP from
get_user_ip()
That means these are counted separately:
GET /api/postsPOST /api/posts- the same route from different client IPs
If the IP cannot be resolved, the limiter falls back to 0.0.0.0, so multiple requests can end up sharing the same bucket.
Response behavior
When a request is allowed, the response gets:
X-RateLimit-Limit
When a request is blocked, the middleware returns a JSON 429 Too Many Requests response with:
X-RateLimit-LimitX-RateLimit-Remaining: 0Retry-After
Blocked responses use this payload:
{"message":"Too Many Requests"}
Important constraints
- Rate limiting only runs on routes that explicitly call
rateLimit(...). - The middleware runs before module middleware.
- The package does not send
X-RateLimit-Remainingon successful requests. - Unsupported adapter names fail with
RateLimitException::adapterNotSupported(...). - Adapter configuration is loaded from
config/rate_limit.phpthe first time the factory is used. - Storage backends report errors differently: file storage returns a blocked hit when lock/state access fails, while Redis client issues may surface as runtime exceptions.