Latest Posts

Running Laravel's queue worker using a cron schedule

Quick Tips

Queues are a powerful tool in the Laravel framework. Inherently, they require some setup - but what about smaller projects?


Laravel's queue facility are great and I use them heavily across a series of large projects and, smaller ones. The problem with queues is that they inherently require a lot of setup, ideally a Redis implementation to manage the jobs, Supervisor to monitor the queue process and ensure it stays running - this isn't ideal in all circumstances.

It's worth noting that this is a quick tip highlighting an alternative approach, and there are multiple ways you can run your queue workers.

What about Horizon?

A great way to manage your queues, particularly for larger projects is installing and utilising Laravel Horizon. That allows you to get a great overview of your queues and queue workers, but that still needs Supervisor to ensure the queue processes continue running. Horizon is great, but what about a project that emits only a few events a day, what about this blog for example?

Run as a cronjob

Did you know that you can run your queue workers as a cronjob? This website uses this exact technique, handling jobs such as contact form submissions or subscriptions. This means that you don't have to wait while we do things in the background.

You can specify the maximum number of seconds a queue worker should be able to run and stop the worker once that time is up and it's finished processing it's final job. Additionally, you can store your jobs at a database level, avoiding the complexity of using a service like Redis.

Setup your migrations

Laravel provides CLI commands out-of-the-box to get your database tables up and running. These tables store your jobs that are due to be run, or that have failed. Running the below command will create the necessary migrations for your queued jobs:

# generate migrations for jobs and failed jobs table
php artisan queue:table
php artisan queue:failed-table

Configure your environment variables

You then need to tell Laravel that you're using the database for processing your queues, that's as simple as setting your QUEUE_CONNECTION environment variable to database.

BROADCAST_CONNECTION=log
FILESYSTEM_DISK=local
QUEUE_CONNECTION=database

Setup your cron schedule

Finally, you need to configure your cron schedule on your production environment, of course this will vary depending on your PHP binaries and where your artisan file is located, but something like the below will do the job nicely:

* * * * * /usr/bin/php [PATH]/artisan queue:work --max-time=60 > /dev/null

You can determine the path you should use above (replace [PATH]) by navigating to the base of your Laravel project and running pwd. This will output the absolute path to your project.

Using this cron schedule, we tell artisan to run the queue worker for a maximum of sixty seconds, and output any response to /dev/null (this prevents accidentally filling up logs)

The cron schedule * * * * * defines that it should be run every minute. So when the first queue worker finishes, the next will begin, and this will continue indefinitely. With the above setup, any jobs added to the queue should get processed in near real time.

Caveats?

I wouldn't recommend this approach for projects handling large volumes of queued jobs, although theoretically it could be done. You'll also need to make sure that your PHP has a max execution time of more than sixty seconds. You can do this by running /usr/bin/php --info | grep max_execution_time. If the response is equal to 0 (infinite) or greater than 60, you're good to go!

If you enjoyed this quick tip, why not consider subscribing for future updates?