Laravel - Queues - Rate Limiting

Although we just demonstrated how to write your own rate limiting job middleware, Laravel actually includes a rate limiting middleware that you may utilize to rate limit jobs. Like route rate limiters, job rate limiters are defined using the RateLimiter facade's for method.

For example, you may wish to allow users to backup their data once per hour while imposing no such limit on premium customers. To accomplish this, you may define a RateLimiter in the boot method of your AppServiceProvider:

    
    use Illuminate\Cache\RateLimiting\Limit;
    use Illuminate\Support\Facades\RateLimiter;
    
    /**
     * Bootstrap any application services.
     *
     * @return void
     */
    public function boot()
    {
        RateLimiter::for('backups', function ($job) {
            return $job->user->vipCustomer()
                        ? Limit::none()
                        : Limit::perHour(1)->by($job->user->id);
        });
    }
	

In the example above, we defined an hourly rate limit; however, you may easily define a rate limit based on minutes using the perMinute method. In addition, you may pass any value you wish to the by method of the rate limit; however, this value is most often used to segment rate limits by customer:

    
    return Limit::perMinute(50)->by($job->user->id);
	

Once you have defined your rate limit, you may attach the rate limiter to your backup job using the Illuminate\Queue\Middleware\RateLimited middleware. Each time the job exceeds the rate limit, this middleware will release the job back to the queue with an appropriate delay based on the rate limit duration.

    
    use Illuminate\Queue\Middleware\RateLimited;
    
    /**
     * Get the middleware the job should pass through.
     *
     * @return array
     */
    public function middleware()
    {
        return [new RateLimited('backups')];
    }
	

Releasing a rate limited job back onto the queue will still increment the job's total number of attempts. You may wish to tune your tries and maxExceptions properties on your job class accordingly. Or, you may wish to use the retryUntil method to define the amount of time until the job should no longer be attempted.

If you do not want a job to be retried when it is rate limited, you may use the dontRelease method:

    
    /**
     * Get the middleware the job should pass through.
     *
     * @return array
     */
    public function middleware()
    {
        return [(new RateLimited('backups'))->dontRelease()];
    }
	
If you are using Redis, you may use the Illuminate\Queue\Middleware\RateLimitedWithRedis middleware, which is fine-tuned for Redis and more efficient than the basic rate limiting middleware.