Start monitoring your Laravel scheduler free — 10 checks, no credit card.
Laravel's task scheduler runs from a single cron entry — `* * * * * php artisan schedule:run` — and that is exactly why scheduler failures are so easy to miss. If that one line stops running (a deploy that drops the crontab, a server reboot, a full disk), every scheduled command silently stops with it and nothing alerts you. Even when the scheduler is running, an individual `Schedule::command()` can throw, exit non-zero, hang past its window, or get silently skipped by `withoutOverlapping`. Laravel's built-in `emailOutputOnFailure` only fires when the command actually ran and failed; it can't tell you about a job that never started or a scheduler that died. The result is the classic blind spot: your nightly backup, queue prune, or data sync quietly stops happening and you only find out when something downstream breaks.
Pakyas is execution-signal based: each scheduled task proves it ran by sending a signal, and Pakyas compares those signals against the task's expected schedule. Laravel ships first-class hooks for exactly this — `pingBefore()`, `thenPing()`, `pingOnSuccess()`, and `pingOnFailure()` — so you wire a Pakyas check into the scheduler definition itself, no wrapper scripts and no SSH-ing into the box to edit crontabs. When a command starts, finishes, or fails, the scheduler pings Pakyas, and Pakyas turns silence and failure into distinct, actionable states: Missing (the signal never arrived, so the task — or the whole scheduler — never ran), Late (it ran outside its expected window), Overrunning (it started but never reported completion), and Error (it explicitly signaled failure with a non-zero exit code). Because the check is defined in source control alongside the task, the monitoring travels with your deploy.
# Laravel needs one cron entry per server to drive schedule:run
* * * * * cd /path-to-your-project && php artisan schedule:run >> /dev/null 2>&1
This single line runs every minute and dispatches all your due tasks. If it ever stops, Pakyas catches the resulting silence as a Missing check (see the optional heartbeat snippet below).
# Sign up at https://pakyas.com and create a check for your scheduled task.
# You get a unique ping URL using the check's public_id (a UUID):
#
# start: https://ping.pakyas.com/{public_id}/start
# success: https://ping.pakyas.com/{public_id}
# fail: https://ping.pakyas.com/{public_id}/fail
#
# Replace {public_id} below with the UUID Pakyas gives you.
GET or POST both work. The bare URL signals success; append /start when the task begins and /fail on a non-zero exit.
<?php
use Illuminate\Support\Facades\Schedule;
// Store the check's base URL in config/env so it isn't hard-coded.
// Add your own key (e.g. PAKYAS_BACKUP_URL) to .env and config/services.php.
$url = config('services.pakyas.backup_url'); // "https://ping.pakyas.com/{public_id}"
Schedule::command('backup:run')
->dailyAt('02:00')
->withoutOverlapping()
->pingBefore($url . '/start') // task is starting
->pingOnSuccess($url) // exit code 0
->pingOnFailure($url . '/fail'); // non-zero exit code
pingBefore / pingOnSuccess / pingOnFailure are built-in Laravel scheduler methods — no extra package required. Define this in routes/console.php (Laravel 11+) or your scheduler closure.
<?php
use Illuminate\Support\Facades\Http;
use Illuminate\Support\Facades\Schedule;
// A separate Pakyas check that pings every minute proves schedule:run is alive.
// Supply your own scheduler check URL via config/env (a second check).
$schedulerUrl = config('services.pakyas.scheduler_url');
Schedule::call(fn () => Http::get($schedulerUrl))
->name('pakyas-scheduler-heartbeat')
->everyMinute();
Set this Pakyas check's expected period to 1 minute. If the crontab dies, the heartbeat stops and Pakyas marks it Missing — catching the failure mode emailOutputOnFailure can never see.
Take a nightly database backup defined as an Artisan command, scheduled with `Schedule::command('backup:run')->dailyAt('02:00')->withoutOverlapping()`. Wire it to a Pakyas check with `->pingBefore($url . '/start')->pingOnSuccess($url)->pingOnFailure($url . '/fail')`. Now: when the backup starts at 02:00 it pings `/start`, so Pakyas knows it began; if it completes cleanly it pings the success URL and the check stays On Schedule; if `backup:run` exits non-zero (S3 credentials expired, disk full) it pings `/fail` and Pakyas marks it Error with the failure captured. And if 02:00 comes and goes with no `/start` at all — because the server rebooted and the `schedule:run` crontab never came back — the check goes Missing and you get alerted, instead of discovering days later that you have no backups.
Pakyas is free for up to 10 checks ($0, no credit card) — enough to monitor the scheduler heartbeat plus your most important commands. Paid tiers add more checks and channels: Developer at $9/mo, Pro at $29/mo, and Business at $99/mo.
See the full breakdown on the pricing page.
New to the terminology? See the cron monitoring glossary for plain-language definitions of every job state, or explore everything Pakyas tracks on the features page.
Start monitoring your Laravel scheduler free — 10 checks, no credit card.
Execution-signal precision: know when a job is Missing, Late, Overrunning, or reports an Error — not just up or down.
Start monitoring free