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.
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
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.
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.
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"}- 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.