I’m always excited to take on new projects and collaborate with innovative teams to build impactful digital solutions.
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.
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.
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.
Laravel supports multiple queue drivers. Each has its own strengths and use cases:
| Driver | Pros | Cons | Use Case |
|---|---|---|---|
| sync | Zero setup | Runs inline, no background processing | Local development, testing |
| database | No extra services needed | Slower, tied to DB performance | Small to medium applications |
| redis | Fast, supports all features | Requires Redis server | Most production apps |
| sqs | Scalable, managed AWS service | AWS dependency, costs | High-scale AWS deployments |
| beanstalkd | Simple, fast | Less common now | Legacy systems |
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...
}
}
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 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 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();
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
php artisan queue:work
// With specific options
php artisan queue:work redis --queue=processing --tries=3 --timeout=120 --sleep=2
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
class UpdateSearchIndex implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
public function uniqueId()
{
return $this->product->id;
}
}
Bus::chain([
new ProcessOrder($order),
new ChargeCustomer($order),
function () use ($order) {
// Send a thank you email
},
])->dispatch();
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.
Your email address will not be published. Required fields are marked *