Monitoring for scheduled jobs: your cron job pings a URL when it starts and finishes, and you are told when a ping does not arrive on time.
Build me cron monitoring that replaces Cronitor: my jobs ping a URL, and I am told when a ping does not arrive. STACK - Node 20+ with Fastify - SQLite through better-sqlite3, WAL mode - A scheduler process separate from the web process — alerting on absence needs something running that is not the thing being watched - Caddy in front THE DATA MODEL - monitors: id, key, name, kind, schedule, timezone, grace_seconds, expected_duration_ms, max_duration_ms, is_active, muted_until, tags_json, created_at - pings: id, monitor_id, event, run_id, exit_code, duration_ms, host, body_excerpt, ip_hash, received_at — event is start, success, fail or log - runs: id, monitor_id, run_id, started_at, ended_at, duration_ms, status, exit_code — assembled from pings - states: monitor_id, status, since, last_ping_at, next_expected_at — the one row the scheduler reads - incidents: id, monitor_id, kind, opened_at, closed_at, cause — kind is late, missing, failed, or too slow - alerts: id, incident_id, channel, target, sent_at, acknowledged_at - Every ping is kept. The archive of when a job ran and how long it took is the thing you cannot reconstruct later THE PING PROTOCOL - GET or POST to /p/:key, with optional /start, /fail and /:exit_code suffixes - A run id, passed as a parameter, pairs a start with its finish — without one, concurrent runs of the same job are indistinguishable and every duration is wrong - A POST body up to a few kilobytes is stored as the run's output, which is what turns 'it failed' into 'it failed because of this' - Answer in a handful of milliseconds and record after responding. The ping must never be what makes a job slow, and it must never make a job fail: document a curl with a timeout and a fallback of true - Idempotent on the run id and event, so a retried ping does not create a second run KNOWING WHEN A JOB IS LATE - The schedule is a cron expression with a time zone, or a simple interval - Compute the next expected time from the schedule, add the grace period, and alert when now passes it with no ping - Time zones and daylight saving handled properly: a job at 02:30 daily has a day each year when that instant does not exist and a day when it happens twice. Decide, document the decision, and test it - The scheduler wakes every few seconds, reads the states table, and acts. It is small, it is separate, and it is the only part of this system that cannot be down quietly - A dead-man's switch for the scheduler itself: it pings an external free service, so 'the monitor stopped monitoring' is noticed BEYOND FAILING - Alert when a job takes longer than its maximum duration, while it is still running - Alert on a trend: duration above the rolling 95th percentile for several runs. A backup that has grown from four minutes to fifty is going to fail in a fortnight - Alert on a non-zero exit code, with the exit code and the captured output in the alert - Flapping suppression: a monitor failing and recovering repeatedly produces one incident, not twenty ALERTS - Email, webhook, chat, and a shell command - Escalation after N minutes unacknowledged, to a second target - Acknowledge from a link in the alert, no login - Recovery messages always, in the same channel - Quiet hours per monitor, with a severity that ignores them THE INTERFACE - One page listing every monitor with its status, last run, next expected and recent durations as a sparkline - A monitor page: the run history, durations over time, the captured output of the last failure - Dark and light, and it must be readable on a phone at three in the morning OPERATIONS - .env: DATABASE_PATH, BASE_URL, SMTP_URL, SESSION_SECRET, HASH_SALT, DEADMAN_URL - Migrations on boot, each once - The ping endpoint is one prepared insert with no joins, and is rate-limited per key generously - Nightly backup off the machine, restore script - Health endpoint that reports the scheduler's last tick WHAT MATTERS MOST The scheduler and the run pairing. Build the states table, the next-expected computation and the start-finish pairing first, then stop a real cron job and confirm you hear about it within the grace period. Alerting on something that did not happen is the entire product, and it is the half that most homemade versions never build. Give me the repository, the scheduler, migrations, .env.example, seed monitors, and a README with deploy steps behind Caddy and the curl line to add to a crontab.
What you lose
- Alerting on absence, which needs a scheduler running somewhere your job is not
- Duration tracking and alerts when a job gets slower rather than only when it fails
- Alert routing to chat, phone and on-call rotas
If you would rather not build
- A cron job that checks a timestamp file
What it costs
read from their page 15 Aug 2026
| Plan | Billed monthly | Billed yearly | Last read |
|---|---|---|---|
| — | $49/mo | — | 15 Aug 2026 |
Their pricing page is where these came from. Seeing a different price? Tell us.
The escape hatch
open source · no votes, no paid placement
Healthchecks
$0Cron job monitoring by ping, self-hostable, with many alert channels.
healthchecks/healthchecksfree · open source
Uptime Kuma
$0Has a push monitor that raises an alert when a ping stops arriving.
louislam/uptime-kumafree · open source
Why this verdict
our own opinion · changed only by a person
86/100
Verdict yes at 86. A ping table and a minute-by-minute query. The heartbeat that proves the monitor is alive is the piece people forget.
History
tracked since 10 Aug 2026 · nothing is ever overwritten
Questions about Cronitor
answered from the record above
Is Cronitor free?
No — the plan we track is $49 a month. Standard from around $49/month billed monthly; a free tier covers a handful of monitors.
Can you replace Cronitor by building your own?
YES. Replaceable in one session with an AI coding agent. Replacement score 86 out of 100, build time one session. Read what you lose before you decide.
How much does Cronitor cost?
$49 a month on Standard — $588 a year. Recorded 10 Aug 2026.
What do you lose by replacing Cronitor?
Alerting on absence, which needs a scheduler running somewhere your job is not; Duration tracking and alerts when a job gets slower rather than only when it fails; Alert routing to chat, phone and on-call rotas. If any of those carry weight for you, keep paying.
Is there an open-source alternative to Cronitor?
Yes: Healthchecks, Uptime Kuma. The prompt on this page is for when you want it your way instead.
Related entries
same category first, most replaced first
Every week, something stops being worth paying for.
New verdicts, prices that moved, entries added. One email a week. Unsubscribe in one click. Nothing is being sent yet — your address is kept here, and the first issue is the first thing it is used for.
free forever · no tracking pixel · stored here, never passed to anyone

