Laravel
Queues & Jobs
Laravel queues allow you to defer time-consuming tasks (emails, notifications, file processing) to background workers, keeping your app fast and responsive.
Queue Driver Config: Set the queue connection in your
.env file. Common drivers: sync (immediate, no worker needed), database, redis, sqs..env
ENV
QUEUE_CONNECTION=database
# For Redis driver
QUEUE_CONNECTION=redis
REDIS_HOST=127.0.0.1
REDIS_PASSWORD=null
REDIS_PORT=6379
Create Jobs Table: When using the
database driver, run these commands to create the jobs and failed_jobs tables.terminal
BASH
php artisan queue:table
php artisan queue:failed-table
php artisan migrate
Creating a Job Class: Use
make:job Artisan command. The handle() method contains the logic that runs in the background.terminal
BASH
php artisan make:job SendWelcomeEmail
app/Jobs/SendWelcomeEmail.php
PHP
<?php
namespace App\Jobs;
use App\Models\User;
use App\Mail\WelcomeMail;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
use Illuminate\Support\Facades\Mail;
class SendWelcomeEmail implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
public int $tries = 3; // Retry up to 3 times on failure
public int $timeout = 60; // Max seconds to run
public function __construct(public User $user) {}
public function handle(): void
{
Mail::to($this->user->email)
->send(new WelcomeMail($this->user));
}
public function failed(\Throwable $exception): void
{
// Called when all retry attempts are exhausted
logger()->error("SendWelcomeEmail failed for user {$this->user->id}: " . $exception->getMessage());
}
}
Dispatching a Job: Use the
dispatch() helper or the static ::dispatch() method from within a controller or service.app/Http/Controllers/RegisterController.php
PHP
use App\Jobs\SendWelcomeEmail;
public function store(Request $request): RedirectResponse
{
$user = User::create($request->validated());
// Dispatch immediately to queue
SendWelcomeEmail::dispatch($user);
// Or using the helper
dispatch(new SendWelcomeEmail($user));
// Dispatch only if a condition is true
SendWelcomeEmail::dispatchIf($user->email_verified_at === null, $user);
return redirect()->route('dashboard');
}
Delay & Chaining: You can delay job execution or chain multiple jobs to run sequentially after one another.
app/Http/Controllers/OrderController.php
PHP
use App\Jobs\ProcessPayment;
use App\Jobs\SendOrderConfirmation;
use App\Jobs\UpdateInventory;
// Delay job by 10 minutes
SendWelcomeEmail::dispatch($user)->delay(now()->addMinutes(10));
// Chain jobs — each runs after the previous succeeds
ProcessPayment::withChain([
new SendOrderConfirmation($order),
new UpdateInventory($order),
])->dispatch($order);
// Using Bus facade for chaining
use Illuminate\Support\Facades\Bus;
Bus::chain([
new ProcessPayment($order),
new SendOrderConfirmation($order),
new UpdateInventory($order),
])->dispatch();
// Dispatch on a specific queue name
SendWelcomeEmail::dispatch($user)->onQueue('emails');
Failed Jobs: Failed jobs are stored in the
failed_jobs table. Use Artisan commands to inspect and retry them.terminal – failed jobs management
BASH
# List all failed jobs
php artisan queue:failed
# Retry a specific failed job by ID
php artisan queue:retry 1
# Retry all failed jobs
php artisan queue:retry all
# Delete a specific failed job
php artisan queue:forget 1
# Flush (delete) all failed jobs
php artisan queue:flush
Running the Queue Worker: The worker processes jobs from the queue. Use
--queue to specify priority queues and --tries to limit retries.terminal – queue worker
BASH
# Start the queue worker (processes jobs continuously)
php artisan queue:work
# Process from a specific connection and queue
php artisan queue:work redis --queue=high,emails,default
# Set max tries and timeout
php artisan queue:work --tries=3 --timeout=90
# Process only one job then stop (useful for cron)
php artisan queue:work --once
# Restart workers gracefully after code deploy
php artisan queue:restart
Laravel Horizon (Redis only): Horizon provides a beautiful dashboard and config-driven control over your Redis-based queues. Install it for production use.
terminal – horizon setup
BASH
composer require laravel/horizon
php artisan horizon:install
php artisan migrate
# Start Horizon (replaces queue:work for Redis)
php artisan horizon
# Pause / continue Horizon
php artisan horizon:pause
php artisan horizon:continue
# Access dashboard at /horizon (protected by HorizonServiceProvider gate)
config/horizon.php (excerpt)
PHP
'environments' => [
'production' => [
'supervisor-1' => [
'connection' => 'redis',
'queue' => ['high', 'emails', 'default'],
'balance' => 'auto',
'processes' => 10,
'tries' => 3,
'timeout' => 60,
],
],
'local' => [
'supervisor-1' => [
'connection' => 'redis',
'queue' => ['default'],
'balance' => 'simple',
'processes' => 3,
'tries' => 3,
],
],
],