Rate Limiting is a powerful feature in Laravel that limits the number of times users or clients can do specific activities within a given time range. This functionality is frequently used to prevent misuse, safeguard resources, and ensure fair usage of APIs and other endpoints. Laravel's rate limiter is based on a caching mechanism and can be readily adjusted to meet a variety of application requirements.
The rate limiter makes use of your application's default cache driver, as specified in the CACHE_STORE
environment variable. Setting the limiter key in your cache configuration allows you to specify a different cache driver to use for rate limiting.
'default' => env('CACHE_STORE', 'database'),
'limiter' => 'redis',
Laravel has a RateLimiter facade for communicating with the rate limiter. The most typical approach is attempt, which limits a callback to a certain number of attempts over a set time period.
Basic Example: Limiting Attempts
use Illuminate\Support\Facades\RateLimiter;
$executed = RateLimiter::attempt(
'send-message:'.$user->id,
$perMinute = 5,
function () {
// Action to perform
}
);
if (! $executed) {
return 'Too many messages sent!';
}
In this case, the action is limited to five attempts per minute. If the limit is exceeded, the callback is terminated and a custom message is returned.
Custom Decay Rates
You can set a custom decay rate (in seconds) for the rate limit:
$executed = RateLimiter::attempt(
'send-message:'.$user->id,
$perTwoMinutes = 5,
function () {
// Action to perform
},
$decayRate = 120
);
The limit allows for five attempts every two minutes.
Laravel offers additional techniques for further control over rate limiting:
Increasing Attempts
You can manually increase the try count on a specific key.
use Illuminate\Support\Facades\RateLimiter;
RateLimiter::increment('send-message:'.$user->id);
// Perform the action
Checking Remaining Attempts
To determine how many attempts remain for a particular key:
if (RateLimiter::remaining('send-message:'.$user->id, 5)) {
RateLimiter::increment('send-message:'.$user->id);
// Perform the action
}
Determining Reset Times
To find out how long till new attempts are available:
if (RateLimiter::tooManyAttempts('send-message:'.$user->id, 5)) {
$seconds = RateLimiter::availableIn('send-message:'.$user->id);
return 'You may try again in '.$seconds.' seconds.';
}
Clearing Attempts
The clear technique can be used to reset a key's attempt count.
RateLimiter::clear('send-message:'.$user->id);
Rate restriction is a typical feature of middleware-based routing. Laravel's ThrottleRequests
middleware makes it simple to establish restrictions on HTTP requests.
Basic Route-Level Throttling
Route::middleware('throttle:60,1')->group(function () {
Route::get('/api/posts', [PostController::class, 'index']);
});
This sets a restriction of 60 requests per minute for the grouped routes.
Define a Custom Limiter
To define a dynamic rate limiter in App\Providers\RouteServiceProvider
:
use Illuminate\Cache\RateLimiting\Limit;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\RateLimiter;
RateLimiter::for('custom', function (Request $request) {
return Limit::perMinute(100)->by($request->user()?->id ?: $request->ip());
});
Then, apply it to routes with:
Route::middleware('throttle:custom')->group(function () {
Route::get('/api/posts', [PostController::class, 'index']);
});
Rate Limiting in Laravel gives developers a powerful, customizable tool for controlling request frequency and protecting their applications. Caching, middleware, and dynamic limiters can be used to efficiently manage resource utilization while keeping a consistent user experience. With correct implementation, Laravel's rate-limiting features may help protect and optimize applications of any size.