Cron monitoring for Laravel and Node.js

Cron monitoring that installs itself.

Add one package to your Laravel or Node.js app and every scheduled job is monitored: run duration, exit codes, and the actual exception when something fails. Anything else can check in with a plain HTTP ping.

// composer require pingark/pingark-laravel
$schedule->command('backup:run')
    ->daily()->pingArk('nightly-backup');
Copy
Free for 20 checks · no card required · any language
checks · production live · polling 15s
Up
nightly-backup
0 2 * * * · UTC
Up
stripe-sync
*/15 * * * *
Down
queue:work
every 5m
no ping 22m
42 up 1 late 1 down 44 checks
queue:work down · alerted #alerts, PagerDuty
Speaks every runtime
curl Laravel Node.js Next.js Nuxt Python Go systemd cron
How it works

Three moving parts. That is the whole idea.

01 · PING

Your job checks in

Drop in the Laravel plugin or the JS SDK, or add a curl at the end of any job. Send start, success, fail, or an exit code.

02 · WATCH

We hold the deadline

We expect the next ping on your schedule plus a grace window. State slides from up to late quietly, with no noise while it is still in grace.

03 · ALERT

You hear about it first

Past grace, or on an explicit failure, we flip it down and notify every channel you have armed. Recovery sends an all-clear.

Drop-in for your stack

One line, wherever the job runs.

The official Laravel package and JavaScript SDK do the heavy lifting: start and finish signals, run duration, exit codes, and exception context, wrapped for the tools you already use. And a bare curl still works from anything that can reach the network.

// routes/console.php or app/Console/Kernel.php
$schedule->command('backup:run')
    ->daily()
    ->pingArk('nightly-backup');
// duration, exit code & exceptions: automatic

// or mirror the whole schedule as checks,
// one credential in .env and you are done
// php artisan pingark:sync
Copy
npm install pingark · composer require pingark/pingark-laravel JavaScript SDK guide Laravel plugin guide
The model

A check has exactly one state.

No dashboards full of ambiguous yellows. Five states, one meaning each, and only down ever pages you.

New Up Late Down · Paused
NEW

Created, inert. No alerts until the first ping arrives.

UP / LATE

Pinging on time. Late is derived inside the grace window. Informational, never paged.

DOWN

Deadline blown or an explicit fail. One alert out; recovery sends the all-clear.

PAUSED

Muted by hand for maintenance. Auto-resumes on the next ping.

Capable, not bloated

Everything a heartbeat monitor should have.

Real schedules

Cron expressions with timezones, simple periods from a minute to a year, and systemd OnCalendar, each with its own grace.

Rich pings

Start and finish for run duration, explicit fail, exit codes, and an optional body for logs and exception context.

Nine alert channels

Email, Slack, Discord, Telegram, webhooks, and PagerDuty on every plan, plus WhatsApp, SMS, and voice call with bundled credits on higher plans.

A real dashboard

A status board, ping timeline, downtime history, and surfaced delivery failures, because a broken alert is the worst kind.

Management API

Create, pause, and list checks over a clean REST API with read-only and read-write keys per project.

Status badges

Drop a live SVG badge into any README so a project's heartbeat is visible at a glance.

Built for Laravel first

Your scheduler, monitored. Zero ceremony.

Chain one method onto a scheduled command and the plugin wraps it: sending start and finish, and capturing duration, exit code, and the exception trace when it throws.

Auto-registers every scheduled task as a check
Run duration from start to success
Exit codes and exception context on failure
Mirror the whole schedule with pingark:sync
See the Laravel integration
// app/Console/Kernel.php
$schedule->command('backup:run')
->daily()
->pingArk('nightly-backup');
// duration, exit code & exceptions: automatic
Copy
$ composer require pingark/pingark-laravel
# then add your project key to .env
PINGARK_PING_KEY=pk_live_a1b2c3d4
Built for Node.js too

Wrap the job. The rest is automatic.

One function around any scheduled job and the SDK reports it: start and finish, run duration, and the actual error with its message when the job throws. Never in the way, never breaking the job.

monitor() wraps any function or promise in one line
The thrown error lands on the check timeline
Adapters for Next.js, Express, and Nuxt included
TypeScript-first, zero dependencies, ESM and CJS
See the JavaScript SDK
// anywhere a job runs: Node.js 18+, Bun, Deno, the edge
import { monitor } from 'pingark'
await monitor(() => runNightlyJob(), 'nightly-job')
// start, finish, duration & the thrown error: automatic
Copy
$ npm install pingark
# then add your project key to .env
PINGARK_PING_KEY=pk_live_a1b2c3d4
Alerts where you already look
All integrations
Email
verified
Slack
webhook
Discord
webhook
Telegram
bot
Webhook
any HTTP
PagerDuty
escalation
WhatsApp
message credits
Premium
SMS
message credits
Premium
Voice call
call credits
Premium
Teams · ntfy · Opsgenie
coming soon
Pricing

Priced on checks, not seats or events.

Start free. Upgrade only when you outgrow your check count.

Free
$0

20 checks · Core monitoring for a side project or two, on us.

Starter
$9 /mo

50 checks · For indie developers running real workloads.

Fleet
$79 /mo

1,000 checks · Higher scale for bigger fleets and agencies.

Compare plans Nonprofit or open source? There is a plan for you.
Founding users get Pro first.

Paid plans are launching soon. Join the founding list and you will get early access to Pro plus a founding-user perk when upgrades open. The founding cohort closes the day paid plans launch.

Start monitoring in two minutes.

One curl line stands between you and never being the last to know.