Laravel Tutorials

Pause All Laravel Queues During a Deploy

Published
Pause All Laravel Queues During a Deploy image

There is a window during most deploys where the code on disk has changed but the workers running against it have not restarted yet. A worker that reserves a job in that window deserializes a payload written by the old code and runs it through the new code. Most of the time nothing happens. Occasionally a renamed job class or a changed constructor signature turns it into a failed job you have to replay by hand.

The usual workaround is maintenance mode, which stops far more than the queue, or queue:restart, which is a request rather than a guarantee since a worker only sees it between jobs. Laravel 13.25 adds a third option: a switch that stops every worker on every connection from reserving new work, without touching HTTP traffic.

The Command

php artisan queue:pause --all

And to undo it:

php artisan queue:resume --all

The queue argument on both commands is now optional, so --all is the only thing you pass. Without the flag they behave as before and take a connection:queue pair.

The same switch is on the Queue facade for deploy scripts written in PHP, or for a controller behind an admin panel:

use Illuminate\Support\Facades\Queue;
 
Queue::pauseAll();
 
// ...
 
Queue::resumeAll();

What Pausing Actually Does

A paused queue stops workers from reserving new jobs. The worker process stays alive and keeps looping, it just sleeps instead of popping. A job already being processed when you pause runs to completion, so a queue:pause --all in a deploy script does not interrupt anything mid-flight. Producers are unaffected too: SomeJob::dispatch() keeps writing to Redis or the database, and those jobs sit there until you resume.

Mechanically it is one cache key, illuminate:queues:paused, written with forever(). Workers already read the cache once per loop to check for restart and per-queue pause signals, and the global key is fetched in the same many() call, so this adds no extra round trips. QueueManager::isPaused() and getPausedQueues() both report a queue as paused when either the global key or its own key is set.

The Two Switches Are Independent

pause() and pauseAll() write different keys, and they are deliberately not aware of each other. If a queue was paused individually, resumeAll() leaves it paused:

Queue::pause('redis', 'imports'); // parked while we investigate a bad job
 
Queue::pauseAll(); // deploy starts
Queue::resumeAll(); // deploy finishes
 
Queue::isPaused('redis', 'imports'); // true

This is the behavior you want in a deploy script. Somebody parked the imports queue on purpose an hour ago, and a deploy running resumeAll() should not quietly undo that. Clearing an individual pause still takes queue:resume redis:imports.

Events

Two events fire alongside the existing per-queue QueuePaused and QueueResumed:

use Illuminate\Queue\Events\QueuesPaused;
use Illuminate\Queue\Events\QueuesResumed;
 
Event::listen(function (QueuesPaused $event) {
Log::warning('All queues paused');
});

Further Reading

Paul Redmond photo

Staff writer at Laravel News. Full stack web developer and author.

Sponsored

laravelcloud logo
Laravel Cloud

Easily create and manage your servers and deploy your Laravel applications in seconds.

Visit Laravel Cloud

The latest

View all →
Look What You Helped Me Build image

Look What You Helped Me Build

Read article
BashBox: A Sandboxed Bash Interpreter for AI Agents in PHP image

BashBox: A Sandboxed Bash Interpreter for AI Agents in PHP

Read article
Running Laravel's Scheduler on Multiple Servers image

Running Laravel's Scheduler on Multiple Servers

Read article
Laravel Fake Assertions Now Accept Property Arrays image

Laravel Fake Assertions Now Accept Property Arrays

Read article
Route::query() and Model defaults() in Laravel 13.35 image

Route::query() and Model defaults() in Laravel 13.35

Read article
Laravel AI SDK 1.1 Adds Agent Skills and Cohere Chat image

Laravel AI SDK 1.1 Adds Agent Skills and Cohere Chat

Read article