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() or tries.
  • 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.


Further Reading

Categorized in: