Introduction
Laravel 13 added two features that change how production apps move jobs between brokers: Queue::route() centralizes the "which connection does this job use?" decision, and the failover driver lets a second broker take over when the primary is down. Before 13, each job had to call onConnection() / onQueue() itself — if you wanted to move all payment jobs to a new Redis cluster, you had to grep the codebase.
Key Concepts
- Queue routing: A rulebook registered once in a service provider that says this job class lives on this connection and queue.
- Failover driver: A meta-driver that wraps two or more real drivers and pushes jobs to the first healthy one.
- Deferred/background connections: Special connection names that run jobs after the HTTP response is flushed, without a worker.
Real World Context
A team moving from a single Redis to a Redis + SQS setup used to sprinkle ->onConnection('sqs') across dozens of controllers. With Queue::route(), the mapping is one file. And when Redis goes down at 3am, the failover driver routes to SQS instead of filling up failed_jobs.
Deep Dive
Centralized routing with Queue::route
Register routes in a service provider so you never repeat onConnection at the call site:
phpuse Illuminate\Support\Facades\Queue; use App\Jobs\ProcessPayment; use App\Jobs\SendReceipt; public function boot(): void { Queue::route(ProcessPayment::class, connection: 'redis', queue: 'payments'); Queue::route(SendReceipt::class, connection: 'sqs', queue: 'emails'); }
Now anywhere in the app you can just write ProcessPayment::dispatch($order) and it lands on the right broker.
The failover driver
Configure a failover connection in config/queue.php:
php'connections' => [ 'redis' => [ 'driver' => 'redis', // ... ], 'sqs' => [ 'driver' => 'sqs', // ... ], 'failover' => [ 'driver' => 'failover', 'connections' => ['redis', 'sqs'], ], ],
Dispatch through the failover connection:
phpProcessReport::dispatch($data)->onConnection('failover');
If pushing to redis throws, Laravel transparently tries sqs — the caller never sees the error.
Deferred and background connections
Laravel 13 formalized two special connection names:
php// Runs after the response is sent — no worker needed SendWelcomeEmail::dispatch($user)->onConnection('deferred'); // Runs in a background PHP process — also no worker needed GenerateThumbnail::dispatch($upload)->onConnection('background');
These replace the older dispatchAfterResponse() helper and give you a clean way to fire-and-forget small jobs without running Supervisor.
Common Pitfalls
- Registering routes inside a controller —
Queue::route()must live in a service provider'sboot()method, or the mapping won't exist when jobs are dispatched from other parts of the app. - Putting SQS first in a failover list — the first driver is the preferred one. If you list SQS first because it's "more reliable", every job pays the network round-trip even when Redis is healthy.
Best Practices
- Route by job class, not by call site — one service-provider file is easier to audit than grepping for
onConnection. - Keep failover lists short (2–3 drivers) — long failover chains mask real outages and make debugging harder.
Summary
Queue::route()maps job classes to connections/queues in one place.- The
failoverdriver tries brokers in order until one succeeds. deferredandbackgroundconnections run small jobs without a worker.