What Are Queues in Laravel

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:

  1. Order placed
  2. Order email sent
  3. Payment confirmation processed
  4. Invoice generated
  5. Download link emailed
  6. Analytics stored
  7. 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

Comments

Leave a Reply

Your email address will not be published. Required fields are marked *