In modern PHP web development, performance is non-negotiable. Users expect snappy interfaces and real-time feedback. However, tasks like sending emails, generating PDFs, or processing images can cause unnecessary delays. Thankfully, Laravel Queues offer an elegant, built-in solution for offloading time-consuming tasks into the background.
In this comprehensive guide, we’ll explore everything you need to know about how to use queues in Laravel, from setup to production-ready deployment, complete with best practices and advanced techniques.
What Are Laravel Queues?
Laravel Queues allow you to defer the execution of tasks such as email sending, file uploads, or notifications, so they can be processed asynchronously by a queue worker in the background.
This improves:
- Application speed – response time is instant
- Scalability – your app can serve more users
- Reliability – jobs can be retried if they fail
Laravel queues are especially useful for large-scale web applications, SaaS platforms, and APIs where performance is critical.
How to Set Up Laravel Queues (Step-by-Step)
Step 1: Choose Your Laravel Queue Driver
Laravel supports several queue backends (drivers), including:
sync
(immediate execution)database
(uses your DB to store jobs)redis
(best for speed)beanstalkd
Amazon SQS
null
(disables queuing)
Update your .env
file:
QUEUE_CONNECTION=database
Tip: Use
redis
for better performance in production environments.
Step 2: Create Jobs in Laravel
Run the Artisan command to create a job class:
php artisan make:job ProcessEmailJob
This will generate a file in app/Jobs/ProcessEmailJob.php
with a basic structure. Add your background logic inside the handle()
method:
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
class ProcessEmailJob implements ShouldQueue
{
use Queueable;
public function __construct(public $user) {}
public function handle()
{
Mail::to($this->user->email)->send(new WelcomeMail($this->user));
}
}
Step 3: Dispatch Jobs to the Queue
Once your job is ready, dispatch it in your controller or service layer:
ProcessEmailJob::dispatch($user);
To delay job execution, use:
ProcessEmailJob::dispatch($user)->delay(now()->addMinutes(5));
Step 4: Create and Run the Queue Worker
For the database driver, generate a jobs table:
php artisan queue:table
php artisan migrate
Then start the queue worker:
php artisan queue:work
Use
php artisan queue:work --daemon
in production for better performance.
You can also set the number of tries, memory limits, and timeout duration:
php artisan queue:work --tries=3 --timeout=90 --memory=128
Handling Failed Jobs in Laravel
When a job throws an exception or exceeds its timeout, Laravel marks it as failed. To store failed jobs:
php artisan queue:failed-table
php artisan migrate
Update .env
:
QUEUE_FAILED_DRIVER=database
Then, monitor or retry failed jobs:
php artisan queue:failed
php artisan queue:retry all
Laravel Horizon: Real-Time Queue Monitoring
For apps using Redis, Laravel Horizon is the ultimate tool for managing queues visually. It provides:
- Job throughput stats
- Retry management
- Failed job inspection
- Real-time dashboards
Install Horizon:
composer require laravel/horizon
php artisan horizon:install
php artisan migrate
Start Horizon:
php artisan horizon
Access the dashboard at /horizon
.
Laravel Queue Best Practices
To ensure efficient background job processing:
- Keep jobs short – Avoid long logic blocks inside the job itself.
- Avoid passing Eloquent models – Use model IDs instead to prevent serialization issues.
- Implement retry logic – Handle transient errors gracefully with
retryUntil()
ortries
. - Monitor queue health – Use Laravel Horizon or a system like Supervisor to restart dead workers.
- Queue in production – Always use queue workers in production for critical tasks.
Supervisor: Running Laravel Queue Workers in Production
Use Supervisor (Linux) to keep your queue workers running 24/7.
Example config (/etc/supervisor/conf.d/laravel-worker.conf
):
[program:laravel-worker]
process_name=%(program_name)s_%(process_num)02d
command=php /var/www/yourapp/artisan queue:work --sleep=3 --tries=3
autostart=true
autorestart=true
user=www-data
numprocs=3
redirect_stderr=true
stdout_logfile=/var/www/yourapp/storage/logs/laravel-queue.log
Restart Supervisor:
sudo supervisorctl reread
sudo supervisorctl update
sudo supervisorctl start laravel-worker:*
Final Thoughts: When to Use Laravel Queues
Use Laravel Queues when:
- You’re sending multiple emails or SMS
- You need real-time notifications
- You’re processing uploads, images, or external API calls
- You want better scalability and faster app responses
By mastering Laravel’s job queue system, you gain a massive performance edge—essential for building responsive, scalable, and modern PHP applications.
Frequently Asked Questions (FAQs)
Q: Can I use Laravel Queues without Redis?
Yes! You can use database
as a queue driver for simpler apps.
Q: What’s the difference between queue:work
and queue:listen
?queue:listen
boots Laravel on every job, slower but safer for development. queue:work
is faster, ideal for production.
Q: How can I schedule queued jobs?
Use Laravel Scheduler to dispatch jobs at specific times.
Comments