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 →
Delete Expired Sessions in Laravel With a Scheduled Command image

Delete Expired Sessions in Laravel With a Scheduled Command

Read article
Pollora: Run WordPress Inside a Laravel Application image

Pollora: Run WordPress Inside a Laravel Application

Read article
Scheduled Session Garbage Collection in Laravel 13.39 image

Scheduled Session Garbage Collection in Laravel 13.39

Read article
Deferred Schema Loading in Filament v5.8 image

Deferred Schema Loading in Filament v5.8

Read article
Sloppy: Static Analysis for AI-Written PHP image

Sloppy: Static Analysis for AI-Written PHP

Read article
Mastering Laravel Testing: A Video Course on Laravel Tests image

Mastering Laravel Testing: A Video Course on Laravel Tests

Read article