I’m always excited to take on new projects and collaborate with innovative teams to build impactful digital solutions.

Social Links

The Complete Guide to Laravel Queues & Jobs: From Basics to Advanced Patterns

Master Laravel queues and jobs with this comprehensive guide covering everything from setup and configuration to advanced patterns like chaining, batching, rate limiting, and job middleware.

Introduction

Queues are one of the most powerful features of Laravel. They allow you to defer time-consuming tasks like sending emails, processing uploads, or hitting third-party APIs, so your application can respond to requests instantly. In this comprehensive guide, we'll take you from the absolute basics to advanced queue patterns that production applications rely on.

Why Use Queues?

Imagine a user signs up on your application. Without queues, the registration request would wait for the confirmation email to send before responding. That email might take 2-3 seconds, making the user wait. With queues, the request completes in milliseconds and the email is processed in the background. This is the fundamental value proposition of queued jobs.

Queue Configuration

Laravel supports multiple queue drivers. Each has its own strengths and use cases:

DriverProsConsUse Case
syncZero setupRuns inline, no background processingLocal development, testing
databaseNo extra services neededSlower, tied to DB performanceSmall to medium applications
redisFast, supports all featuresRequires Redis serverMost production apps
sqsScalable, managed AWS serviceAWS dependency, costsHigh-scale AWS deployments
beanstalkdSimple, fastLess common nowLegacy systems

Creating Your First Job

Jobs are generated with a simple Artisan command:

php artisan make:job ProcessPodcast

This creates a class in app/Jobs. The job has a handle method where the magic happens:

<?php

namespace App\Jobs;

use App\Models\Podcast;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Queue\Queueable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;

class ProcessPodcast implements ShouldQueue
{
    use Queueable, InteractsWithQueue, SerializesModels;

    public function __construct(
        public Podcast $podcast,
    ) {}

    public function handle(): void
    {
        // Process the podcast episode...
    }
}

Dispatching Jobs

There are several ways to dispatch a job. The most convenient is the dispatch helper:

ProcessPodcast::dispatch($podcast);

// With a delay
ProcessPodcast::dispatch($podcast)->delay(now()->addMinutes(10));

// On a specific connection
ProcessPodcast::dispatch($podcast)->onConnection('redis');

// On a specific queue
ProcessPodcast::dispatch($podcast)->onQueue('processing');

// Chain multiple jobs
ProcessPodcast::withChain([
    new OptimizePodcast($podcast),
    new ReleasePodcast($podcast),
])->dispatch();

Job Middleware

Job middleware allow you to wrap custom logic around the execution of queued jobs. A classic example is rate limiting external API calls:

<?php

namespace App\Jobs\Middleware;

class RateLimited
{
    public function handle($job, $next)
    {
        Redis::throttle('key')
            ->block(60)
            ->allow(10)
            ->then(function () use ($job, $next) {
                $next($job);
            }, function () use ($job) {
                $job->release(30);
            });
    }
}

Job Batching

Job batching lets you execute a set of jobs and then perform a final action when they all complete. This is perfect for bulk operations:

use Illuminate\Support\Facades\Bus;

$batch = Bus::batch([
    new ImportCsvRow(1),
    new ImportCsvRow(2),
    new ImportCsvRow(3),
])->then(function (Batch $batch) {
    // All jobs completed successfully...
})->catch(function (Batch $batch, Throwable $e) {
    // First batch job failure detected...
})->finally(function (Batch $batch) {
    // The batch has finished executing...
})->dispatch();

Handling Failures

When a job fails, Laravel records it in the failed_jobs table. You can retry failed jobs:

php artisan queue:retry all
php artisan queue:retry 8d5e3f2a-1c2d-4e5f-8a9b-0c1d2e3f4a5b

You can also define how many times a job should be attempted and the timeout:

public $tries = 5;
public $timeout = 120;
public $backoff = [2, 10, 60]; // Exponential backoff in seconds

Running the Queue Worker

php artisan queue:work

// With specific options
php artisan queue:work redis --queue=processing --tries=3 --timeout=120 --sleep=2

Supervisor Configuration for Production

In production, queue workers should run as daemons under a process monitor like Supervisor:

[program:laravel-worker]
process_name=%(program_name)s_%(process_num)02d
command=php /home/forge/example.com/artisan queue:work redis --sleep=3 --tries=3 --max-time=3600
autostart=true
autorestart=true
stopasgroup=true
killasgroup=true
user=forge
numprocs=8
redirect_stderr=true
stdout_logfile=/home/forge/example.com/worker.log
stopwaitsecs=3600

Advanced Patterns

Unique Jobs

class UpdateSearchIndex implements ShouldQueue
{
    use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;

    public function uniqueId()
    {
        return $this->product->id;
    }
}

Job Chaining with Closures

Bus::chain([
    new ProcessOrder($order),
    new ChargeCustomer($order),
    function () use ($order) {
        // Send a thank you email
    },
])->dispatch();

Conclusion

Queues transform your application's responsiveness and scalability. Start simple with the database driver, then graduate to Redis as your traffic grows. Master batching and middleware to unlock truly advanced workflows. Your users will thank you for the instant responses.

4 min read
Aug 08, 2026
By Developer Shadin
Share

Leave a comment

Your email address will not be published. Required fields are marked *