Laravel Queues are one of the most powerful features in the framework. They allow your application to handle heavy, time-consuming, or asynchronous tasks in the background. Instead of making users wait while emails are being sent, reports are generated, or video files are processed, Laravel’s queue system offloads those tasks to background workers. This improves performance, user experience, scalability, and application responsiveness.
In this 3000-word guide, you will learn everything about queues in Laravel: what they are, why they are necessary, how queue drivers work, how to create jobs, dispatch jobs, manage workers, retry jobs, handle failed jobs, monitor queues, integrate with Redis, SQS, and database queues, and how to use them for scalable background processing.
By the end of this guide, you will understand queues at both foundational and advanced levels.
Understanding the Concept of Queues
A queue is a storage mechanism for tasks that need to run in the background.
Tasks added to the queue include:
- sending emails
- generating reports
- processing images
- storing analytics
- synchronizing data
- uploading files
- clearing cache
- running imports/exports
Queues separate long-running tasks from the main request cycle.
This means when a user submits a form or loads a page, they do not have to wait for slow tasks to finish.
Why Queues Are Important in Web Applications
Without queues, users experience delays. For example:
- Registration page takes long because an email is being sent
- Checkout takes long because a PDF invoice is generated
- Image upload is slow because resizing happens in real time
Queues solve these issues by pushing tasks to be processed later.
Queues help with:
- speed
- performance
- user satisfaction
- reliability
- fault tolerance
- system scalability
When traffic increases, queues ensure tasks continue processing smoothly.
How Laravel Implements Queues
Laravel provides a unified queue API that supports multiple backends.
You can switch queue drivers without changing application code.
Supported drivers:
- database
- Redis
- Amazon SQS
- Beanstalkd
- SQS FIFO
- synchronous (sync)
- null (discard tasks)
Configuration file:
config/queue.php
Default driver:
QUEUE_CONNECTION=sync
Sync driver runs tasks instantly without background processing. For real queuing, you must change this to:
QUEUE_CONNECTION=database
Or Redis, or SQS.
Queue Drivers Explained
Database Driver
Stores queued jobs inside a database table.
Good for small to medium projects.
Create jobs table:
php artisan queue:table
php artisan migrate
Jobs are stored in:
jobs
failed_jobs
Redis Driver
Redis is the fastest queue backend.
Supports heavy traffic and real-time applications.
Requires Redis to be installed and configured.
Amazon SQS
Cloud-based queue service from AWS.
Used for enterprise-level scalability.
Beanstalkd
Lightweight job queue service.
Used in high-performance systems.
Creating a Job in Laravel
Jobs hold the logic you want to run in the background.
Create a job:
php artisan make:job SendEmailJob
This generates a file inside:
app/Jobs/SendEmailJob.php
Basic structure:
class SendEmailJob implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
public function __construct()
{
}
public function handle()
{
// background logic here
}
}
Key part:
implements ShouldQueue
This tells Laravel that the job should go to the queue.
Dispatching a Job
Dispatch the job using:
SendEmailJob::dispatch();
Or pass data:
SendEmailJob::dispatch($user);
This pushes the job to the selected queue driver.
Running the Queue Worker
To process jobs, start the queue worker:
php artisan queue:work
This listens for new jobs and processes them immediately.
If the worker stops, jobs will remain pending.
In production, workers run continuously using Supervisor or systemd.
queue:listen vs queue:work
queue:listen restarts the framework on every job.
queue:work is faster and should be used in production.
Use:
php artisan queue:work
For debugging:
php artisan queue:listen
Using Queues to Send Emails
Slowest operation in most applications is sending emails.
Queues make this fast.
Controller example:
SendEmailJob::dispatch($user);
Job example:
public function handle()
{
Mail::to($this->user->email)->send(new WelcomeMail($this->user));
}
User sees instant response.
Email sends in background.
Using Queues to Process Images
Image resizing is expensive.
Queues help offload work.
ImageProcessingJob::dispatch($imagePath);
Image processing logic in handle():
$img = Image::make($path);
$img->resize(1200, null, function ($constraint) {
$constraint->aspectRatio();
});
$img->save();
Generating Large Reports With Queues
Large PDF or CSV reports should be queued.
GenerateReportJob::dispatch();
This prevents timeout errors and improves UX.
Queue Priorities
You can define priority queues.
Dispatch to high priority:
SendEmailJob::dispatch()->onQueue('high');
Low priority:
->onQueue('low');
Start workers by queue:
php artisan queue:work --queue=high,default,low
High priority jobs run first.
Delayed Jobs
Delay job execution:
SendEmailJob::dispatch()->delay(now()->addMinutes(10));
Laravel schedules job for later execution.
Rate Limiting Jobs
Prevent job overload:
public $tries = 5;
Limits number of retries.
You can also throttle processing speed.
Using Middleware With Jobs
Middleware for jobs works like HTTP middleware.
Inside job:
public function middleware()
{
return [new WithoutOverlapping('emails')];
}
This prevents job duplication.
Handling Failed Jobs
If a job fails, Laravel places it in failed_jobs table.
Enable:
php artisan queue:failed-table
php artisan migrate
Retry failed jobs:
php artisan queue:retry all
Delete failed jobs:
php artisan queue:flush
Retrying Jobs Automatically
Inside job:
public $tries = 3;
public $timeout = 60;
Laravel retries the job three times.
Handling Exceptions in Jobs
Use try-catch:
public function handle()
{
try {
// logic
} catch (\Exception $e) {
Log::error($e->getMessage());
}
}
Or let job fail naturally.
Dispatching Jobs Synchronously
Process immediately:
SendEmailJob::dispatchSync();
Useful for debugging.
Using Job Batching
Batch multiple jobs:
Bus::batch([
new JobOne,
new JobTwo,
])->dispatch();
Monitor batch completion.
Using Chains of Jobs
Run jobs in sequence:
Bus::chain([
new StepOne,
new StepTwo,
])->dispatch();
StepTwo runs only after StepOne finishes.
Queues and Database Transactions
Use afterCommit() to dispatch after DB transaction completes:
SendEmailJob::dispatch()->afterCommit();
Supervisors for Queue Workers
In production, workers must run forever.
Use Supervisor on Linux.
Supervisor config example:
[program:laravel-worker]
command=php /var/www/artisan queue:work
numprocs=3
autostart=true
autorestart=true
user=www-data
Restart:
sudo supervisorctl reload
Redis Queues in Laravel
Install Redis:
composer require predis/predis
Change driver:
QUEUE_CONNECTION=redis
Redis queues are extremely fast.
SQS Queues for Enterprise Applications
Configure in .env:
QUEUE_CONNECTION=sqs
Best for cloud-based scalable systems.
Horizon for Queue Monitoring
Laravel Horizon provides queue dashboards.
Install:
composer require laravel/horizon
Publish:
php artisan horizon:install
php artisan migrate
View dashboard at:
/horizon
Horizon shows:
- job status
- queue size
- failed jobs
- processing time
Queues and Notifications
Laravel notifications can run through queues.
public $afterCommit = true;
Or set:
implements ShouldQueue
Email notifications now send in background.
Advanced Queue Strategies
Distributing Workload
Use multiple workers:
php artisan queue:work --queue=high
php artisan queue:work --queue=default
Multiple Queues Per Connection
QUEUE_CONNECTION=redis
Routes queues:
->onQueue('emails')
->onQueue('reports')
Monitor Queue Health
Use horizon, logs, or custom monitoring.
Common Mistakes With Queues
Avoid:
- using sync driver in production
- dispatching heavy jobs without queues
- forgetting to run the worker
- not setting retries
- ignoring failed jobs
- placing too much logic in controllers instead of jobs
When to Use Queues vs Scheduled Tasks
Queues are for:
- background tasks
- event-driven actions
- heavy processing
Scheduling (cron) is for:
- daily backups
- hourly cleanup
- nightly reports
Queues are event-based, scheduling is time-based.
Real-World Example: Order Processing System
Steps:
- Order placed
- Order email sent
- Payment confirmation processed
- Invoice generated
- Download link emailed
- Analytics stored
- Inventory updated
Each step is a job.
Chaining jobs creates a smooth workflow.
Best Practices for Using Queues
- Use Redis for large applications
- Store logs for failed jobs
- Use Supervisor to keep workers alive
- Separate queues by priority
- Limit long-running jobs
- Batch or chain related tasks
- Use DTOs to pass data
- Keep handle() clean and simple
Leave a Reply