Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

davidrushton's avatar

Database Queue on Shared Hosting

Sometimes it's necessary to host a Laravel app on shared / cPanel hosting, but we recently ran in to an issue where using the queue was necessary.

Given that Beanstalkd, SQS and Redis weren't possible, we looked into using the database driver and a the scheduler cron job.

Thought I'd post the solution we used here in case it's helpful for anyone else. The code is on Gist at https://gist.github.com/davidrushton/b7229df4c73372402fc1 and I wrote a quick blog post at http://papertank.co.uk/blog/903/setup-laravel-queue-on-shared-hosting/.

Thanks to inspiration from https://gist.github.com/mauris/11375869, the scheduler job which runs every 5 minutes spawns a new queue:listen process and checks a local file with the process ID to see if it needs re-created or not.

0 likes
14 replies
daem0n's avatar

The solution I used that might be more resource efficient is this

$schedule->command('queue:work --daemon')->everyMinute()->withoutOverlapping();

Curious to hear your thoughts on this approach. It uses laravel's native withoutOverlapping logic that doing similar to what your solution is doing with the pid file. I think laravel just stores it in the storage dir.

2 likes
davidrushton's avatar

@daem0n Just looking at that withoutOverlapping method - interesting.

It looks like Laravel might use the description of the task rather than the process id, so this might not handle if the process is killed for some reason outside of Laravel, i'm not sure.

Have you had any issues with using queue:work --daemon on your shared hosting?

daem0n's avatar

Nope, its been solid so far. I used kill -9 on the process manually from another ssh session and sure enough it kickstarted it back up the next minute the cron job ran :)

The benefit is that the worker daemon keeps the same copy of the app code running, so its a bit more efficient. I also read in other threads that the queue:work --daemon is preferred over queue:listen.

daem0n's avatar

sweet, would love to hear how it turns out for you. I've had it going for just over a day now myself haha

1 like
davidrushton's avatar

@daem0n Just a quick update - I tried the queue:work --daemon setup but it looked like this was keeping the schedule:run command going and was creating several new queue:work commands.

I might not have set it up right, but I've gone back to the other setup for now.

1 like
pilat's avatar

Here's a one-liner to put into your crontab (let it run, let say, every 5 minutes):

cd /path/to/your/project && jobs -l | grep `cat queue.pid` || { nohup /usr/bin/php artisan queue:listen & echo $! > queue.pid; }

two variables here:

  1. /path/to/your/project — your Laravel project root. Effectively, the folder, where php artisan would work;
  2. /usr/bin/php — path to PHP executable on the server (can be found `which p)

The script would check if there is a job with PID, stored in queue.pid file. If No, it would start a new job and write its PID into the file.

pilat's avatar

A comment on my previous note: the solution has proven not to work if CRON Job is run by sh. With bash it should work.

Another approach, which has finally worked for me:

flock -n /tmp/latavel_queues.lockfile /usr/bin/php /path/to/laravel/artisan queue:listen

Hint: first check if flock is available on your server. I was lucky :-)

samfrjn11's avatar

I have the same problem. The cronjob keeps the schedule:run live. The cron is running every minute and gives errors saying that "schedule:run" is already running (because schedule:run is never finished due to queue:work being still active)

Going to try out @davidrushton's solution

henryonsoftware's avatar

I found this solution after 2 days research and GG help.

I write this function on app/Console/Kernel.php

protected function osProcessIsRunning($needle)
    {
        // get process status. the "-ww"-option is important to get the full output!
        exec('ps aux -ww', $process_status);

        // search $needle in process status
        $result = array_filter($process_status, function($var) use ($needle) {
            return strpos($var, $needle);
        });

        // if the result is not empty, the needle exists in running processes
        if (!empty($result)) {
            return true;
        }
        return false;
    }

And this code to call it in method schedule()

// start the queue worker, if its not running
if (!$this->osProcessIsRunning('queue:work')) {
    $schedule->command('queue:work')->everyMinute();
}
10 likes
pilat's avatar

Regarding the command: here's the lates "edition", which I haven't changed for the last year, maybe… See that it has -xn and -c arguments now.

flock -xn /tmp/laravel_queues.lockfile -c "/usr/bin/php /path/to/laravel/artisan queue:listen"

This revision did not pose any issues that I know of.

1 like
dutta's avatar

ohh thank you very much.. finally i have solution for my cronjob is not working. thank you very much

beyond's avatar

@dutta Please can you put me through, I am facing the same problem?

Please or to participate in this conversation.