Laravel throttle, RateLimiter vs ThrottleRequests, when to use which?

669 Views Asked by At

I need to rate limiting for my REST API. Currently I just need rate limit based on the URL prefix, e.g. url with tps/xxx will need a rate limit for 10 times in 1 minute. I may need to add more rules later, e.g. set up different rate limits for different paths.

I see laravel document explain RateLimiter but I also see it mentions ThrottleRequests middleware. After further checking the source codes I see ThrottleRequests does Constructor Injection RateLimiter

    /**
     * Create a new request throttler.
     *
     * @param  \Illuminate\Cache\RateLimiter  $limiter
     * @return void
     */
    public function __construct(RateLimiter $limiter)
    {
        $this->limiter = $limiter;
    }

But it is still unclear to me these two classes's use case and when to use which ?

For my use case based on url prefix, which one should I use ?

--- update ---

I did some further research and found this article How to implement Rate Limiting in Laravel,

There are two ways to implement rate limiting with Laravel:

  1. Using the Rate Limiter Middleware(throttle): to rate limiting incoming HTTP requests before reaching the controller
  2. Using the Rate Limiting abstraction: to interact more finely with the rate limiter at the controller level

But it also adds more question, "The configuration can be changed in /app/Providers/RouteServiceProvider in the configureRateLimiting() method" but I can't find much information about configureRateLimiting(at least not from laravel official documentation).

3

There are 3 best solutions below

0
Encoder - Abdukodir Khojiyev On

When working with Laravel, understanding the difference between throttle, RateLimiter, and ThrottleRequests is crucial for effective rate limiting in your application.

Throttle:

The throttle middleware is a general-purpose middleware that you can use to throttle various aspects of your application. It allows you to set the maximum number of requests that can be made in a given time period. You can use it in your routes or controllers to limit the rate at which users can access certain resources.

Route::middleware('throttle:60,1')->group(function () {
    // Your routes
});

In this example, it allows 60 requests per minute.

RateLimiter:

Rate limiting is critical for protecting app or website resources from excessive or improper use. Whether a result of malicious human intervention, bot-based attacks, or an overlooked vulnerability, resource misuse can interfere with legitimate access to your application and introduce severe vulnerabilities. Laravel's RateLimiter is a more low-level tool that allows you to manage rate limiting programmatically. It provides a set of methods to manage and check the rate limits. Example:

$key = 'user:' . $user->id;
$limiter = app(RateLimiter::class);

if ($limiter->tooManyAttempts($key, $maxAttempts, $decayMinutes)) {
    // Handle rate limit exceeded
} else {
    $limiter->hit($key, $decayMinutes);
    // Continue with the action
}

This allows you to have fine-grained control over rate limiting logic. ThrottleRequests: ThrottleRequests is a trait that you can use in your controllers to apply rate limiting on specific controller actions. It provides an easy way to apply rate limiting to specific methods within your controllers.

This is useful when you want to apply rate limiting only to specific actions.

Use the throttle middleware when you want a quick and easy way to apply rate limiting to your routes. Use RateLimiter when you need more control over rate limiting and want to manage it programmatically. Use ThrottleRequests when you want to apply rate limiting specifically to certain methods within your controllers.

3
Rashid On

RateLimiter:

RateLimiter is used for complex scenarios that requires custom logics for calculating limits and handling responses. Like if you need to limit new users 10 requests per day while regular users 50 requests per day. You can even limit based on suspicious activity like too many downloads in short time. You can do all the stuff with complex custom rules or you can create your own custom logics using RateLimiter. It's flexible, but takes time and effort.

ThrottleRequests:

Throttle is easier to use with pre-built middleware and route annotations for common rate limiting scenarios. For url limits, you should use throttle. It handles basic website traffic flow quickly and simply.

// Define routes with the specific prefix
Route::prefix('tps')
->group(function () {
    Route::get('/xxx', function () {
        // ...
    })->middleware('throttle:10,1'); // 10 requests per minute for routes under /tps/xxx
    // Other routes within the prefix
});
0
Qiulang On

About configureRateLimiting and Rate limiters I find it was introduced in laravel 8.x, check the 8.x Release Notes, https://laravel.com/docs/8.x/releases#improved-rate-limiting

Laravel's request rate limiter feature has been augmented with more flexibility and power, while still maintaining backwards compatibility with previous release's throttle middleware API.

Rate limiters are defined using the RateLimiter facade's for method. The for method accepts a rate limiter name and a closure that returns the limit configuration that should apply to routes that are assigned this rate limiter: ...

Rate limiters may be attached to routes or route groups using the throttle middleware. The throttle middleware accepts the name of the rate limiter you wish to assign to the route:

The Upgrade Guide from 7.x to 8.0, https://laravel.com/docs/8.x/upgrade#routing gives the sample code for configureRateLimiting

I further check the source code for 9.x & 10.x and find 10.x remove the configureRateLimiting.

  1. 9.x : https://github.com/laravel/laravel/blob/9.x/app/Providers/RouteServiceProvider.php
    protected function configureRateLimiting()
    {
        RateLimiter::for('api', function (Request $request) {
            return Limit::perMinute(60)->by($request->user()?->id ?: $request->ip());
        });
    }
  1. 10.x: https://github.com/laravel/laravel/blob/10.x/app/Providers/RouteServiceProvider.php
public function boot(): void
    {
        //The following line was in configureRateLimiting in 8.x & 9.x
        RateLimiter::for('api', function (Request $request) {
            return Limit::perMinute(60)->by($request->user()?->id ?: $request->ip());
        });

       ...
    }

Back to my question, there are more than one way to do throttle in lavavel, it depends on how complex you want your rule to be.