How to monitor Laravel scheduled tasks

To monitor a Laravel scheduled task, use the scheduler's built-in ping methods: pingBefore when the task starts, pingOnSuccess when it succeeds and pingOnFailure when it fails. Cronomonitor alerts you on a failure, and when the pings stop because the task or the whole scheduler isn't running.

Why monitor it

Laravel's scheduler relies on a single cron entry that runs php artisan schedule:run every minute. If that entry is missing on a new server, or the server's cron stops, every scheduled task stops at once, and nothing in Laravel reports it.

1. Create a check

Sign up for Cronomonitor, create a project and add a check named after the job. Give it the job's schedule, here the cron expression 0 3 * * * (every day at 3am, UTC), and a grace period that covers how long the job normally takes.

The check gives you a unique ping URL. Every snippet below is also on the check's page in the dashboard, already filled in with that URL and schedule.

2. Add the ping to your job

routes/console.php
use Illuminate\Support\Facades\Schedule;

Schedule::command('your:command')
    ->cron('0 3 * * *')
    ->pingBefore('https://cronomonitor.com/api/ping/<your-check-id>/start')
    ->pingOnSuccess('https://cronomonitor.com/api/ping/<your-check-id>')
    ->pingOnFailure('https://cronomonitor.com/api/ping/<your-check-id>/fail');

How it works

pingBefore runs as the task starts, so Cronomonitor can time it; pingOnSuccess and pingOnFailure report how it ended. Laravel sends these with its HTTP client, which is included by default.

This uses the Schedule facade in routes/console.php (Laravel 11 and later). On older versions, chain the same methods onto $schedule->command(...) in app/Console/Kernel.php.

Make sure the scheduler itself runs

The server needs one cron entry: * * * * * cd /path-to-your-project && php artisan schedule:run >> /dev/null 2>&1. Monitoring each task covers this too: if the entry goes missing, every check's pings stop and you're alerted.

Long tasks and several servers

Add withoutOverlapping() so a slow run doesn't overlap the next one, and onOneServer() if the app runs on more than one server, so the task, and its pings, run once rather than once per server.

3. Test it

Run the job once by hand, or use Send a test ping on the check. The check turns green as soon as the first ping arrives, and from then on Cronomonitor expects the next one on schedule.

To check where alerts go, use Send test alert on the check. To see a real failure alert, make the job exit with an error once.

If the check says the job didn't run

php artisan schedule:list shows each task's schedule and when it next runs.

php artisan schedule:test runs a chosen task now, which also sends its pings.

Check the server's crontab with crontab -l for the user that runs PHP.

Try it on your own jobs

14-day free trial with every feature. No card required.

Start your free trial