Copied!
Programming
Laravel
PHP
Redis

Laravel Queue Drivers Explained – Database vs Redis vs Amazon SQS

Laravel Queue Drivers Explained – Database vs Redis vs Amazon SQS
Shahroz Javed
Mar 14, 2026 . 71 views

Driver Comparison at a Glance

Laravel supports multiple queue backends. The right choice depends on your infrastructure, traffic, and budget. Here's the honest breakdown:

  • sync — runs jobs immediately in the same process. No queue, no worker. Use only in local development or testing.

  • database — stores jobs in a MySQL/PostgreSQL table. Zero extra infrastructure. Works on any shared hosting. Best for small to medium apps (<100 jobs/minute).

  • redis — stores jobs in Redis (in-memory). Much faster than database. Supports Laravel Horizon for real-time monitoring. Best for production apps with high job volume.

  • Amazon SQS — fully managed, serverless queue. No worker management. Scales to millions of jobs. Best for AWS-hosted applications or when you don't want to manage infrastructure.

  • beanstalkd — lightweight dedicated queue server. Less popular today. Redis is a better choice in most cases.

Database Driver – Setup & Deep Dive

The database driver is the easiest to get started with because you already have a database. Jobs are stored in a jobs table and workers poll it on a set interval.

Step 1: Configure .env

QUEUE_CONNECTION=database

Step 2: Create the Jobs Table

php artisan queue:table
php artisan migrate

This creates the jobs table with these columns:

id           - bigint (primary key)
queue        - varchar (queue name, e.g. "default", "emails")
payload      - longtext (serialized job class + data)
attempts     - tinyint (how many times it's been tried)
reserved_at  - timestamp (when a worker picked it up)
available_at - timestamp (when it becomes available, for delayed jobs)
created_at   - timestamp

Step 3: Create the Failed Jobs Table

php artisan queue:failed-table
php artisan migrate

Step 4: Run the Worker

php artisan queue:work database --queue=emails,default --tries=3

How the Database Driver Works Internally

The worker uses a SELECT + UPDATE pattern to "lock" a job atomically so two workers don't pick up the same job. It sets reserved_at on the row, processes it, then deletes it. This works fine for low to medium job volumes but creates database load at high throughput because every job = multiple database writes.

The Problem with Database Queue at Scale

At high job throughput (1000+ jobs/minute), the constant polling and row locking creates significant database load. The jobs table becomes a bottleneck. This is the point where you should migrate to Redis.

⚠️ Database queue polling interval is controlled by --sleep=3 (seconds). Lower values mean faster job pickup but more DB queries when the queue is empty.

Redis Driver – Setup & Deep Dive

Redis stores your jobs in memory, making it orders of magnitude faster than the database driver. It uses blocking list operations so workers are notified of new jobs instantly — no polling needed.

Step 1: Install Predis

composer require predis/predis

Step 2: Configure .env

QUEUE_CONNECTION=redis
REDIS_CLIENT=predis
REDIS_HOST=127.0.0.1
REDIS_PASSWORD=null
REDIS_PORT=6379

Step 3: Configure database.php

// config/database.php — redis section
'redis' => [
    'client' => env('REDIS_CLIENT', 'predis'),
    'default' => [
        'host'     => env('REDIS_HOST', '127.0.0.1'),
        'password' => env('REDIS_PASSWORD', null),
        'port'     => env('REDIS_PORT', 6379),
        'database' => env('REDIS_DB', 0),
    ],
    'cache' => [
        'host'     => env('REDIS_HOST', '127.0.0.1'),
        'password' => env('REDIS_PASSWORD', null),
        'port'     => env('REDIS_PORT', 6379),
        'database' => env('REDIS_CACHE_DB', 1),
    ],
],
⚠️ Use a separate Redis database index for cache vs queue. Set REDIS_DB=0 for queues and REDIS_CACHE_DB=1 for cache. This prevents cache flushes from wiping your pending jobs.

Step 4: Run the Worker

php artisan queue:work redis --queue=emails,default --tries=3

phpredis vs predis

Laravel supports two Redis PHP clients:

  • predis — pure PHP library. No PHP extension needed. Easy to install with Composer. Slightly slower but good enough for most apps.

  • phpredis — C extension. Faster than predis. Requires installing the PHP extension on the server. Use this in high-throughput production environments.

Laravel Horizon — Redis Queue Monitoring

When using Redis, you can install Laravel Horizon for a beautiful dashboard to monitor your queues in real time — job throughput, wait times, failed jobs, and more:

composer require laravel/horizon
php artisan horizon:install
php artisan horizon

Horizon replaces queue:work as your queue runner and adds metrics, auto-scaling worker counts, and a web dashboard at /horizon.

💡 Related: Laravel Horizon deserves its own full blog post — it transforms how you manage Redis queues in production.

Amazon SQS – Setup & Deep Dive

Amazon SQS is a fully managed message queue service. You don't manage any servers — AWS handles availability, scaling, and delivery. If your app runs on AWS, SQS is often the best choice.

Step 1: Install the AWS SDK

composer require aws/aws-sdk-php ~3.0

Step 2: Create an SQS Queue in AWS Console

  1. Go to AWS Console → SQS → Create Queue

  2. Choose Standard (not FIFO) for most Laravel use cases

  3. Note the Queue URL (e.g. https://sqs.us-east-1.amazonaws.com/123456789/my-queue)

  4. Create an IAM user with sqs:* permissions and note the Access Key and Secret

Step 3: Configure .env

QUEUE_CONNECTION=sqs
AWS_ACCESS_KEY_ID=your-access-key
AWS_SECRET_ACCESS_KEY=your-secret-key
AWS_DEFAULT_REGION=us-east-1
SQS_QUEUE=https://sqs.us-east-1.amazonaws.com/123456789/my-queue
SQS_PREFIX=https://sqs.us-east-1.amazonaws.com/123456789

Step 4: Configure config/queue.php

'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'),
    'suffix'      => env('SQS_SUFFIX'),
    'region'      => env('AWS_DEFAULT_REGION', 'us-east-1'),
    'after_commit' => false,
],

SQS Message Visibility Timeout

SQS has an important concept called visibility timeout. When a worker picks up a job, SQS hides it from other workers for the visibility timeout duration. If the job doesn't finish in time, it becomes visible again and another worker picks it up.

Set your SQS visibility timeout to match (or slightly exceed) your job's $timeout value. Mismatch here causes duplicate job processing — a common SQS gotcha.

⚠️ SQS has a maximum message size of 256KB. If your job payload is larger (e.g. base64 encoded files), you'll get errors. Always pass references (IDs, paths) in your job, not the actual data.

SQS Standard vs FIFO

  • Standard Queue — at-least-once delivery, best-effort ordering. Highest throughput. Use for most Laravel jobs.

  • FIFO Queue — exactly-once delivery, strict ordering. Lower throughput (3000 messages/second max). Use when job order and deduplication are critical (e.g. financial transactions).

Using Multiple Connections Together

You're not limited to one queue connection. You can use different connections for different jobs in the same application — for example, Redis for high-priority emails and SQS for bulk processing:

// Dispatch to Redis queue
SendWelcomeEmail::dispatch($user)
    ->onConnection('redis')
    ->onQueue('emails');

// Dispatch to SQS for bulk work
ProcessBulkExport::dispatch($export)
    ->onConnection('sqs')
    ->onQueue('exports');

You can also set connection and queue as properties on the job class:

class ProcessBulkExport implements ShouldQueue
{
    public string $connection = 'sqs';
    public string $queue = 'exports';
    // ...
}

Conclusion

Choosing the right queue driver is an infrastructure decision that affects performance, cost, and reliability. Here's a simple decision guide:

  • Use database — you're on shared hosting, just starting out, or have low job volume

  • Use redis — you have a VPS/dedicated server, need speed, or want Horizon monitoring

  • Use SQS — your app is on AWS, you need infinite scale, or you want zero queue-server management

  • Use multiple connections — route different job types to the most appropriate backend

📑 On This Page