A job middleware to rate limit jobs
Recently we released a new small package called laravel-rate-limited-job-middleware. As the name implies, this package can be used to limit how many times a job may be executed in a given amount of time.
In this short blog post, I'd like to introduce the package to you.
A possible use case
I'm currently working on a new package to send out emails to a list of subscribers. Mails are being sent out using the many email sending services Laravel supports. All emails will also be sent via a queue.
The email sending services often have a limit on how many emails you are allowed to send in a short amount of time. So I needed a way to rate-limit the number of jobs there are sent within a given amount of time.
In Laravel 6, job middleware was introduced. The example in the Laravel docs showed how to throttle jobs using Redis. This was precisely what I needed, so I decided to package up that example code. I added some methods to customize the behavior.
Introducing laravel-rate-limited-job-middleware
The package can be installed via Composer (no surprises there).
composer require spatie/laravel-rate-limited-job-middleware
You can use the RateLimited
middleware by letting the middleware
method of your job return it.
namespace App\Jobs;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Spatie\RateLimitedMiddleware\RateLimited;
class TestJob implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable;
public function handle()
{
// your job logic
}
public function middleware()
{
return [new RateLimited()];
}
}
By default, this will rate limit your job: only five jobs are allowed to execute per second.
Of course, you can modify that behavior. Here's an example where only 30 jobs are allowed in a timeframe of 60 seconds. The surplus of jobs will be released (which is a fancy word for rescheduled) to be rerun in 90 seconds.
// in your job
public function middleware()
{
$rateLimitedMiddleware = (new RateLimited())
->allow(30)
->everySeconds(60)
->releaseAfterSeconds(90);
return [$rateLimitedMiddleware];
When using rate limiting, the number of attempts of your job may be hard to predict. Instead of using a fixed amount of attempts, it's better to use time-based attempts.
In closing
The package contains a few other interesting methods. To know about them, head over to the docs on GitHub.
Be sure to also check out this big list of packages my team and I have previously made.
What are your thoughts on "A job middleware to rate limit jobs"?