loading...

★ A job middleware to rate limit jobs

freekmurze profile image Freek Van der Herten Originally published at freek.dev on ・2 min read

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.

Discussion

pic
Editor guide