Persistent processes: queue workers, Horizon and your own programs always running
Some applications need something shared hosting didn't have: a program that never ends. A worker that processes the queue as soon as a job arrives, Horizon, a message consumer or a bot.
Until now the way out was a cron job. In Laravel, the scheduler launches a queue:work --stop-when-empty every minute, which processes whatever is pending and stops. It works, but a welcome email can take up to a minute to go out, and anything that has to stay alive all the time, like Horizon, had nowhere to live.
Now, on the Avanza, Max and Elastic plans, you have persistent processes: programs your account keeps running at all times.
What you can keep running
In Hosting → your service → Tools → Processes there's a new block, Persistent processes. Click Add process and choose:
- Queue worker:
php artisan queue:workwith the queues you specify, in order of priority. If jobs pile up, you can add several on the same queues. - Horizon:
php artisan horizon, which manages its own workers and comes with its dashboard and metrics. - Custom command: a shell line for Symfony Messenger, a message consumer, a bot or any program that works in the background.
You set the application folder and, for the worker and Horizon, the PHP version they have to run with. In less than a minute the process goes from Starting to Running.
Avanza allows 3 processes, Max 5 and Elastic 8.
If it goes down, it starts again by itself
A watchdog checks the account's processes every minute and starts any that are down. If the program ends on its own, for example when a worker reaches its --max-time to free memory, it starts again within a second and picks up the version published at that moment.
What it doesn't do is keep trying forever. If a process goes down five times in a row right after starting, it stays Failed and waits for you to restart it, so it doesn't waste your account's CPU on something that can't start.
To find out why, each process has its own log, with a line every time it starts and another every time it ends. The line before each crash almost always explains the cause: a mistyped folder, a missing PHP extension or a service the application can't reach. You fix it and click Restart.
From the same panel you stop, start, edit or delete them. Everything runs as your account's user and within its resources, the same ones your websites use.
With Deploy+, without having to remember to restart
A worker loads the code when it starts and keeps it in memory, so after publishing a new version it has to be restarted. With Deploy+ you don't have to do anything: at the end of every deployment, and also when rolling back to a previous version, it restarts that application's persistent processes. Each worker finishes the job it's working on and starts with the new code, and the deployment log shows how each one ended up.
If you connect a Laravel project, the Deploy+ wizard itself offers to keep its queue worker running, with the folder already filled in.
What it doesn't cover
A persistent process is for background work. It isn't for programs that listen on a port, such as a Node.js server, a Python application or Laravel Reverb. For WebSockets in Laravel we recommend a Pusher-compatible service, such as Ably or Pusher itself, which Laravel supports out of the box; we explain it in WebSockets in Laravel. If your project needs its own server, what you need is a VPS.
There are no persistent processes on Inicia, Webmaster or the accounts within a multi-account hosting. Queues can still be processed with the scheduler, with up to a minute's wait.
If you use Horizon or want your queues in Redis, also take a look at persistent Redis, which arrives at the same time. And you'll find the step by step, with the states, the options for each type and what to do if one is left failed, in the persistent processes guide.