Fix queued jobs that are not being processed
A queued job is a task your application put aside to do later: send an email, resize an image, call an API. A queue worker is the long-running process that picks those tasks up. If jobs pile up and nothing happens, the worker is not running, is looking at the wrong queue, or is running old code.
This article follows the quickest path to the cause: confirm the worker exists and is running, restart it, make its settings match your application, and check what the application itself says. SrvYard supervises the worker with Supervisor, which restarts it if it crashes, so a stopped worker nearly always has a reason you can read.
Before you begin
- A queue driver that is not
sync. WithQUEUE_CONNECTION=sync, jobs run immediately inside the web request and no worker is needed. Fordatabase,redisand similar, a worker is required. Check it under Environment in the site. - Rights. Seeing the processes needs view access to the site; changing them needs permission to manage queues (
sites:manage-queues). See Roles and permissions. - A rough count. How many jobs are waiting, and for how long? Jobs that fail are a different problem from jobs that never start, and the checks differ.
A worker holds your application's code in memory. After a deployment it keeps running the old code until it restarts. SrvYard's default deploy script restarts queue workers for you (the $RESTART_QUEUES() line). If you wrote your own script, make sure it does the same.
1. Find the worker
Open the site and choose Processes.
- Add background process. Creates a worker or any other long-running command. Use it if the list is empty.
- The worker row. Shows the name, the full command (here
php artisan queue:work redis --sleep=3 --tries=3 --max-time=3600), how many Processes run in parallel and the Status. Running is what you want. Anything else on a worker you expect to be busy is your lead. - Scheduler. The Scheduled jobs card shows the Laravel scheduler line (
schedule:run, every minute). The scheduler is a separate thing: it dispatches scheduled jobs, the worker runs queued ones. If scheduled tasks never get queued, check this line first.
If there is no worker at all, that is the whole problem: nothing ever consumed the queue. Create one in step 3.
A site that uses Laravel Horizon has a different shape.
- php artisan horizon. One supervised process. Horizon starts and manages its own worker processes according to
config/horizon.php, so a single row is normal. The dashboard at/horizonshows the queues and workers.
2. Restart the worker
Open the actions menu at the end of the worker's row.
- Restart. Stops the workers and starts them again, so they load the current code and configuration. This is the first thing to try after a deployment or an
.envchange. A restart is graceful for a worker between jobs, but a job that is running when you restart may be interrupted. - View logs. Opens the process's own log file. A worker that crashes at once writes the exception here. If SrvYard cannot read the file at the moment, the panel says so; check the server's connection.
- Edit. Change the command, the number of processes or the user. The menu also has Start, Stop and Delete.
If the status is Stopped or Failed, press Start or Restart and then watch the log. A worker that stops again within seconds has a command that fails: a wrong PHP path, a missing artisan, a PHP version that was removed, or an exception in your boot code.
3. Make the settings match your application
A worker that runs but processes nothing usually listens to a different queue than your application writes to. Open the new-process panel to see the options that matter.
- Queue worker. The preset that builds the
queue:workcommand. Custom lets you type any command. - Preview. The exact command that Supervisor will run. Compare it with your application's configuration.
- Create background process. Saves it and starts it.
The options to compare:
| Option | What it must match |
|---|---|
| connection | QUEUE_CONNECTION in the site's .env (redis, database, sqs ...). A worker on database will never see jobs in redis. |
| --queue | The queue names your jobs are dispatched to, comma separated, in priority order, for example high,default. Jobs on a queue the worker does not list wait forever. |
| processes | How many workers run in parallel. Raise it if jobs arrive faster than they finish. |
| --tries and --backoff | How often and how soon a failed job is retried. |
| --timeout | How long one job may run. It must be lower than the retry setting of the connection (retry_after), or jobs run twice. |
| --memory | The worker restarts itself when it uses more than this many MB. A very low value makes it restart constantly. |
| php | The PHP version. Use the same as the site. |
A --timeout shorter than your slowest job kills it halfway, and it is retried. Set it above the longest legitimate job.
4. Check the application's view
If the worker is running and the settings match, look at the application:
- Queue backend. For
redis, check that the Redis service is running on the server (Services) and thatREDIS_HOSTand the password in.envare right. Fordatabase, check that thejobstable exists (runphp artisan migrate). - Failed jobs. Run
php artisan queue:failedunder Commands on the site. Failed jobs mean the worker is fine and your jobs throw exceptions: fix the code, thenphp artisan queue:retry all. - Maintenance mode. A worker does not process jobs while the application is down for maintenance unless it runs with
--force. - Scheduled tasks that never run. Check the scheduler line in step 1, and that the cron job is Installed.
- Memory. A worker that the system kills for using too much memory shows up as repeated restarts in its log. See Disk full, out of memory or a slow server.
5. Test the worker end to end
Do not wait for a real job to find out. Dispatch a harmless one and watch it go through:
- In Commands on the site, run
php artisan tinker --execute 'dispatch(fn () => logger("queue test"));'. - Open Logs, choose the Laravel log and press Refresh. A line reading
queue testappears within a few seconds if the worker is healthy. - If nothing appears, open Processes, check the status of the worker again and read its log with View logs.
Keep this check in mind after every change to the queue connection, the PHP version or the Redis password. All three have broken workers silently before.
Troubleshooting
- Jobs run twice. The job takes longer than the connection's
retry_after, so it is handed out again. Raiseretry_afterabove--timeout, or shorten the job. - Jobs run old code after a deploy. The workers were not restarted. Add the restart to the deploy script, or press Restart by hand.
- The worker row shows 0 processes. The process count was set to zero or the program failed to start. Edit it and read the log.
- It works on my machine but not here. Your local queue is probably
sync. CompareQUEUE_CONNECTIONin both.envfiles. - Horizon says "inactive" in its dashboard. The supervised
php artisan horizonprocess is stopped; start it from Processes. Horizon also needs the queue connection to be Redis. - Only one of two sites processes jobs. Each site has its own workers. Check Processes on the other site.
Related
- Queue workers and the Laravel scheduler: the full guide to creating them.
- Background processes for a site: how Supervisor processes work.
- Write and test a deploy script: where the worker restart belongs.
- Disk full, out of memory or a slow server: when workers are killed.