Introduction

Queues let you defer time-consuming work — sending email, generating PDFs, calling a third-party API — so your HTTP responses stay fast. Instead of making a user wait while a 2-second email send finishes, you push a job onto a queue and return immediately.

Key Concepts

  • Queue: A FIFO list of pending jobs waiting to be processed.
  • Driver: The backend that stores the queue — database, Redis, SQS, Beanstalkd, or sync (which runs inline).
  • Worker: A long-running PHP process that pulls jobs off the queue and executes them.
  • Job: A PHP class that encapsulates a unit of background work.

Real World Context

Every production Laravel app uses queues. A checkout flow might dispatch a payment-charge job, a receipt-email job, and an analytics-tracking job before returning the redirect — all in under 10ms, instead of the 5+ seconds those would take synchronously. Without queues, your app scales by the slowest downstream service you call.

Deep Dive

Why Use Queues?

Without Queues:                 With Queues:
┌──────────────────┐            ┌──────────────────┐
│  User Request    │            │  User Request    │
└────────┬─────────┘            └────────┬─────────┘
         │                                │
         ▼                                ▼
┌──────────────────┐            ┌──────────────────┐
│  Process Order   │            │  Process Order   │
│   (100ms)        │            │   (100ms)        │
└────────┬─────────┘            └────────┬─────────┘
         │                                │
         ▼                                ▼
┌──────────────────┐            ┌──────────────────┐
│  Send Email      │            │  Queue Email Job │ ◄── Returns immediately!
│   (2000ms)       │            │   (5ms)          │
└────────┬─────────┘            └────────┬─────────┘
         │                                │
         ▼                                ▼
┌──────────────────┐            ┌──────────────────┐
│  Generate PDF    │            │  Response: 105ms │
│   (3000ms)       │            └──────────────────┘
└────────┬─────────┘
         │                      Background Worker:
         ▼                      ┌──────────────────┐
┌──────────────────┐            │  Send Email      │
│  Response: 5100ms│            │  Generate PDF    │
└──────────────────┘            │  (No user wait)  │
                                └──────────────────┘

Queue Benefits

BenefitDescription
Faster ResponsesUsers don't wait for slow operations
Better UXImmediate feedback, background processing
ScalabilityAdd more workers to handle load
ReliabilityRetry failed jobs automatically
Resource ManagementControl when heavy tasks run

Queue Drivers

Laravel supports multiple queue backends:

php
// config/queue.php
'connections' => [
    'database' => [
        'driver' => 'database',
        'connection' => env('DB_QUEUE_CONNECTION'),
        'table' => env('DB_QUEUE_TABLE', 'jobs'),
        'queue' => env('DB_QUEUE', 'default'),
        'retry_after' => (int) env('DB_QUEUE_RETRY_AFTER', 90),
        'after_commit' => false,
    ],

    'redis' => [
        'driver' => 'redis',
        'connection' => env('REDIS_QUEUE_CONNECTION', 'default'),
        'queue' => env('REDIS_QUEUE', 'default'),
        'retry_after' => (int) env('REDIS_QUEUE_RETRY_AFTER', 90),
        'block_for' => null,
        'after_commit' => false,
    ],

    'sqs' => [
        'driver' => 'sqs',
        'key' => env('AWS_ACCESS_KEY_ID'),
        'secret' => env('AWS_SECRET_ACCESS_KEY'),
        'prefix' => env('SQS_PREFIX', 'https://sqs.us-east-1.amazonaws.com/your-account-id'),
        'queue' => env('SQS_QUEUE', 'default'),
        'region' => env('AWS_DEFAULT_REGION', 'us-east-1'),
        'after_commit' => false,
    ],

    'sync' => [
        'driver' => 'sync',  // Runs immediately (good for testing)
    ],
],

Choosing a Driver

DriverUse Case
syncLocal development, testing
databaseSimple apps, getting started
redisProduction apps, fast performance
sqsAWS deployments, high scale
beanstalkdAlternative to Redis

Database Queue Setup

Laravel 13 includes queue migrations by default:

bash
# If you need to create them manually
php artisan make:queue-table
php artisan migrate

The jobs table structure:

php
Schema::create('jobs', function (Blueprint $table) {
    $table->id();
    $table->string('queue')->index();
    $table->longText('payload');
    $table->unsignedTinyInteger('attempts');
    $table->unsignedInteger('reserved_at')->nullable();
    $table->unsignedInteger('available_at');
    $table->unsignedInteger('created_at');
});

Configuring the Queue Connection

env
# .env
QUEUE_CONNECTION=database

# For Redis
QUEUE_CONNECTION=redis
REDIS_HOST=127.0.0.1
REDIS_PASSWORD=null
REDIS_PORT=6379

Running Queue Workers

bash
# Start processing jobs
php artisan queue:work

# Process jobs from specific queue
php artisan queue:work --queue=high,default,low

# Process single job and exit
php artisan queue:work --once

# With configuration options
php artisan queue:work --tries=3 --timeout=60 --memory=128

Note: the Laravel 13 docs only document queue:work for running jobs. Use it everywhere — in production under Supervisor, and in development by restarting the worker whenever you change job code.

The Development Server

Laravel 13's composer dev runs everything together:

bash
composer dev
# Runs: server, queue:work, pail (logs), and vite concurrently

Common Pitfalls

  1. Forgetting to start a worker — jobs dispatched with no queue:work process running pile up in the queue forever. In development, use composer dev (or the sync driver) so background tasks actually run.
  2. Using sync in production — the sync driver runs jobs inline in the request, defeating the whole point of queues. It's meant for tests and local experiments, never for real traffic.

Best Practices

  1. Start with database, upgrade to redis when you have load — database needs no extra infrastructure, but row contention and polling hurt above a few hundred jobs per minute. Redis is flat until tens of thousands per second.
  2. Use composer dev for local development — it starts the server, worker, log tail, and Vite bundler together so you never forget to boot a worker.

Summary

  • Queues defer slow work from the HTTP request cycle to background workers.
  • Laravel supports sync, database, redis, sqs, and beanstalkd drivers.
  • Jobs are PHP classes dispatched from controllers and executed by queue:work.
  • Production: queue:work under Supervisor. Development: composer dev.
✓ Completed