June 10, 2025

Understanding Queues in Laravel – A Beginner-Friendly Guide

If you’ve ever built a Laravel app that sends emails, processes images, or talks to external APIs, you might have noticed something:
some tasks take time — and while they run, your users are stuck waiting.

That’s where queues come in. Queues let you push time-consuming work into the background, so your app can respond to users instantly.


1. What is a Queue in Laravel?

A queue is like a to-do list for your application.
When something needs to be done but doesn’t have to happen right now, you can push it onto the queue. Later, a worker process will pick it up and handle it.

Example tasks perfect for queues:

  • Sending a welcome email
  • Resizing uploaded images
  • Generating PDF reports
  • Processing payments with third-party APIs

2. How Laravel Queues Work

Here’s the basic flow:

  1. You dispatch a Job — Laravel saves the job’s details in a storage system (database, Redis, Amazon SQS, etc.).
  2. A queue worker runs in the background, watching for new jobs.
  3. When a job is found, the worker processes it.
  4. Once done, the job is marked as complete (or failed if something went wrong).

It’s just like writing tasks on sticky notes, putting them in a box, and having someone else work through them one by one.


3. Drivers: Where Are Jobs Stored?

Laravel supports multiple queue drivers, meaning your jobs can be stored in different places:

  • Database – Jobs stored in a jobs table. Easy to set up, but slower than in-memory options.
  • Redis – Fast, in-memory storage. Great for high performance and real-time systems.
  • Amazon SQS – Fully managed queue service in AWS.
  • Beanstalkd – Lightweight, fast queue server.
  • Sync – Doesn’t queue at all; runs immediately (used for testing).

4. Creating a Job

Let’s create a job to send a welcome email.

php artisan make:job SendWelcomeEmail

Laravel creates app/Jobs/SendWelcomeEmail.php:

class SendWelcomeEmail implements ShouldQueue
{
    use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;

    public function __construct(public $user) {}

    public function handle()
    {
        Mail::to($this->user->email)->send(new WelcomeMail($this->user));
    }
}

Key points:

  • ShouldQueue tells Laravel this job should go into the queue.
  • handle() is the method that actually runs when the worker processes the job.

5. Dispatching a Job

In your controller or service:

SendWelcomeEmail::dispatch($user);

This pushes the job into the queue defined in your .env file:

QUEUE_CONNECTION=database

6. Processing Jobs with Workers

A queue won’t process jobs until you start a worker.

php artisan queue:work

This command runs a worker that:

  • Listens to the queue
  • Picks up jobs
  • Runs them

In production, you don’t want to start workers manually — you’ll use Supervisor or a process manager to keep them running.


7. Example with Multiple Queues

You can have different queues for different tasks:

SendWelcomeEmail::dispatch($user)->onQueue('emails');
GenerateReport::dispatch($data)->onQueue('reports');

Start workers for specific queues:

php artisan queue:work --queue=emails
php artisan queue:work --queue=reports

This way, heavy jobs don’t block urgent ones.


8. Failed Jobs

Sometimes jobs fail (network issues, bugs, etc.). Laravel can store them in a failed_jobs table.

Enable it:

php artisan queue:failed-table
php artisan migrate

Then you can retry them:

bashCopyEditphp artisan queue:retry all

9. Choosing Between Database and Redis

Database Queue

  • ✅ Easy to set up
  • ❌ Slower (reads/writes from disk)
  • ✅ Works if Redis isn’t available

Redis Queue

  • ✅ Very fast (in-memory)
  • ✅ Good for high concurrency
  • ❌ Requires Redis installed & running

Both are asynchronous in Laravel — your code doesn’t wait for the job to finish.


10. Quick Summary

  • Queues help you run tasks in the background.
  • You dispatch jobs and workers process them.
  • Laravel supports multiple queue drivers (database, Redis, SQS, etc.).
  • Use Supervisor in production to keep workers alive.
  • Store failed jobs and retry them when needed.

Final Tip:
If you have a high-traffic app, use Redis for speed, separate queues for different priorities, and always monitor failed jobs.