My team at Spatie is currenlty building Mailcoach, a solution to self host your e-mail newsletter. Mailcoach can be used a stand alone software or as a Laravel package. Subscribe now at Mailcoach to get a notification as soon as we release it.

A job middleware to rate limit jobs

Original – by Freek Van der Herten – 3 minute 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.

Stay up to date with all things Laravel, PHP, and JavaScript.

Follow me on Twitter. I regularly tweet out programming tips, and what I myself have learned in ongoing projects.

Every two weeks I send out a newsletter containing lots of interesting stuff for the modern PHP developer.

Expect quick tips & tricks, interesting tutorials, opinions and packages. Because I work with Laravel every day there is an emphasis on that framework.

Rest assured that I will only use your email address to send you the newsletter and will not use it for any other purposes.

Comments

You can comment on this post by replying to this tweet.
Jess Archer replied on 7th November 2019
Ahh, gotcha! I'd thought it was installed in an existing app - similar to nova, etc. I'm looking forward to trying it!
Reno Philibert liked on 10th October 2019
atymic liked on 10th October 2019
Spatie retweeted on 9th October 2019
Daniel Ramirez 🍂 liked on 9th October 2019
이현석 Hyunseok Lee liked on 9th October 2019
austin kregel liked on 9th October 2019
Mike liked on 9th October 2019
Arputharaj retweeted on 9th October 2019
Cyril de Wit liked on 8th October 2019
Ryan Chandler liked on 8th October 2019
mahmod liked on 8th October 2019
Benjamin Crozat liked on 8th October 2019
oluwajubelo loves VueJS 🚨 liked on 8th October 2019
Hayk D liked on 8th October 2019
Jimmy Lipham liked on 8th October 2019
Chris SFR liked on 8th October 2019
Hayk D retweeted on 8th October 2019