Updated June 2026. Tested on Laravel 13 and PHP 8.4. Part of the Techalyst queue series. See also Laravel queues and deployments.
Restarting workers belongs in every deploy script, because workers run the code they booted with. The command is simple.
php artisan queue:restart
But sometimes you run it, and the workers keep happily running old code. Before you panic, understand how the restart actually works, because the failure is almost always one of three things.
How queue:restart really works
queue:restart does not signal the worker processes directly. It writes a key, illuminate:queue:restart, into your cache store, holding the timestamp of when the command ran. After finishing each job, every worker checks that cache key and compares it to the last time it looked. If the timestamp is newer, the worker exits gracefully, and your process manager starts a fresh one.
That indirect, cache-based mechanism is the key to understanding the failures: anything that stops a worker from seeing the same cache key stops the restart.
You can confirm whether a worker actually restarted by checking its uptime in your process manager (Forge shows this directly). A freshly restarted worker reads uptime 0 days, 00:00:20. If the uptime is long after a restart, the signal did not reach it.
Cause 1: you are using queue:listen, not queue:work
If you start workers with queue:listen instead of queue:work, restarting has no effect, and that is by design. queue:listen already boots a fresh child process for every single job, so it always runs the latest code without needing a restart. There is no long lived booted app to recycle. The only way to restart a listen process is manually through your process manager.
supervisorctl restart worker-name:*
Cause 2: the workers and the restart command use different cache stores
The restart command writes the cache key, and the workers read it. If they are not pointed at the same cache store, the workers never see the key, and never restart. All instances running your app must share one cache store for this to work.
If you use the file cache driver, this commonly shows up as a permissions problem: the user running queue:restart writes the key to storage/framework/cache, but the worker processes run as a different user and cannot read it. Make the cache directory ownership consistent.
sudo chown -R forge:forge storage/framework/cache
Now whether the restart command or the workers touch those files, they are the same user and can both read and write the key.
Cause 3: you changed the cache prefix
This one is sneaky. The cache key is stored under your cache prefix. If you change the prefix, queue:restart writes the key under the new prefix, but the already-running workers, booted before the change, are still looking under the old prefix. They never see the new key.
So after changing your cache prefix, the running workers will not pick up the restart signal at all. You have to restart them manually once.
supervisorctl restart worker-name:*
After that one manual restart, the fresh workers use the new prefix and queue:restart works again.
Wrapping up
queue:restart works by setting a cache key that workers check between jobs, so it fails whenever a worker cannot see that key. The three usual suspects: you are running queue:listen (which never needs restarting and ignores the signal), the workers and the command use different cache stores or have file cache permission mismatches, or you changed the cache prefix and the old workers are watching the old key. Check uptime to confirm, and restart manually through your process manager when the cache based signal cannot reach them.
More in the series: Laravel queue workers: how they work and Laravel queues and deployments. Questions welcome below.
All comments ()
No comments yet
Be the first to leave a comment on this post.