Queues & Jobs
LaravelQueues allow you to defer time-consuming tasks (sending emails, processing images, making API calls) to be run in the background, keeping your app fast and responsive.
Why Use Queues?
Without Queue (Slow)
User submits form
→ PHP sends email (takes 2-3 seconds)
→ PHP resizes image (takes 1-2 seconds)
→ PHP calls external API (takes 1-3 seconds)
→ Response returned after 6-8 seconds (bad UX!)With Queue (Fast)
User submits form
→ PHP dispatches jobs to queue (instant)
→ Response returned in milliseconds ✅
→ Queue worker processes jobs in backgroundSetup Queue
.env
# Use database queue (simplest setup)
QUEUE_CONNECTION=database
# Or Redis (faster, for production)
QUEUE_CONNECTION=redis
REDIS_HOST=127.0.0.1
REDIS_PORT=6379Terminal
# Create jobs table (for database queue)
php artisan queue:table
php artisan migrate
# Create a job class
php artisan make:job SendWelcomeEmailCreating a Job
app/Jobs/SendWelcomeEmail.php
<?php
namespace App\Jobs;
use App\Models\User;
use App\Mail\WelcomeEmail;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Mail\Mailable;
use Illuminate\Support\Facades\Mail;
class SendWelcomeEmail implements ShouldQueue
{
use Queueable;
public int $tries = 3; // Retry 3 times if it fails
public int $timeout = 60; // Max 60 seconds
public function __construct(
public User $user
) {}
public function handle(): void
{
Mail::to($this->user->email)
->send(new WelcomeEmail($this->user));
}
public function failed(Throwable $exception): void
{
// Log the failure, notify admin, etc.
Log::error("Failed to send welcome email to {$this->user->email}");
}
}Dispatching Jobs
PHP — In Controller
<?php
// Dispatch immediately to queue
SendWelcomeEmail::dispatch($user);
// Dispatch with delay (send after 10 minutes)
SendWelcomeEmail::dispatch($user)->delay(now()->addMinutes(10));
// Dispatch to specific queue
SendWelcomeEmail::dispatch($user)->onQueue('emails');
// Dispatch only if condition is true
SendWelcomeEmail::dispatchIf($user->wantsEmails, $user);
// Dispatch synchronously (no queue, for testing)
SendWelcomeEmail::dispatchSync($user);Running the Queue Worker
Terminal
# Start worker (processes jobs)
php artisan queue:work
# Work a specific queue
php artisan queue:work --queue=emails,default
# Process only one job then stop
php artisan queue:work --once
# In production — use Supervisor to keep worker running
# /etc/supervisor/conf.d/laravel-worker.conf
[program:laravel-worker]
command=php /var/www/html/artisan queue:work --sleep=3 --tries=3
autostart=true
autorestart=trueScheduled Tasks
app/Console/Kernel.php
<?php
protected function schedule(Schedule $schedule): void
{
// Run every day at midnight
$schedule->job(new CleanupOldFiles)->daily();
// Run every hour
$schedule->command('reports:generate')->hourly();
// Run every Monday at 9am
$schedule->command('emails:weekly-digest')->weeklyOn(1, '9:00');
}
// Add to crontab (runs scheduler every minute):
// * * * * * php /var/www/html/artisan schedule:run💡
Use Redis in production! Database queues work for low traffic but Redis is much faster. On AWS, use ElastiCache for Redis. Horizon (Laravel's queue dashboard) requires Redis too.
Test your knowledge!
Take the Laravel quiz.