Healthchecks.io
Replaceable in one session with an AI coding agent.
Monitoring for scheduled jobs by absence: your cron job pings a URL when it finishes, and you are told when a ping does not arrive on time.
Build me cron monitoring that replaces Healthchecks — and note that it is open source with a generous free tier, so build this for the schema rather than the saving. 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, **on a machine that is not the one running your jobs** THE DATA MODEL - monitors: id, key, name, schedule, timezone, grace_seconds, expected_duration_ms, max_duration_ms, is_active, muted_until, tags_json - 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 — late, missing, failed or too slow - alerts: id, incident_id, channel, target, sent_at, acknowledged_at - Every ping kept. The archive of when a job ran and how long it took is the thing you cannot reconstruct THE PING PROTOCOL - GET or POST to /p/:key, with optional /start, /fail and /:exit_code suffixes - A run id 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 stored as the run's output, which turns 'it failed' into 'it failed because of this' - Answer in a handful of milliseconds and record after responding. The ping must never make a job slow, and it must never make one fail: document a curl with a timeout and a fallback of true - Idempotent on 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, add the grace period, and alert when now passes it with no ping - Daylight saving handled properly: a daily job at 02:30 has a day each year when that instant does not exist and a day when it happens twice. Decide, document, and test it - The scheduler wakes every few seconds, reads the states table and acts. It is small, separate, and the only part that cannot be down quietly - **A dead-man's switch for the scheduler itself**, pinging a free external service, so 'the monitor stopped monitoring' is noticed BEYOND FAILING - Alert when a job exceeds 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 will fail in a fortnight - Alert on a non-zero exit code, with the code and the captured output in the message - Flapping suppressed: repeated failure and recovery produces one incident, not twenty ALERTS - Email, webhook, chat and a shell command; escalation after N minutes unacknowledged - Acknowledge from a link in the alert, no login; recovery messages always, in the same channel - Muting with an end time, never indefinitely 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 - Nightly backup off the machine, restore script - Health endpoint reporting 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, 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 homemade versions never build.
What you lose
- A scheduler running somewhere your job is not, which is the only place absence can be noticed
- Alert routing to email, chat, phone and on-call rotas, already wired
- A generous free tier, which makes the money argument thin
- Somebody else keeping the thing that watches your jobs running
If you would rather not build
- A cron entry that curls a URL, plus a scheduler that notices when it stops, which is the whole idea
The escape hatch
open source · no votes, no paid placement
Healthchecks
$0The product itself: cron monitoring by absence, self-hostable.
healthchecks/healthchecksfree · open source
Uptime Kuma
$0Self-hosted monitoring with push checks alongside HTTP and TCP.
louislam/uptime-kumafree · open source
Why this verdict
our own opinion · changed only by a person
88/100
Verdict yes at 88: a ping endpoint, a states table and a small scheduler. The free tier is generous enough that the reason to build is wanting the archive on your own machine, and the entry says where the real work is.
History
tracked since 14 Aug 2026 · nothing is ever overwritten
Questions about Healthchecks.io
answered from the record above
Is Healthchecks.io free?
No — the plan we track is $5 a month. Business from $5/month billed monthly for 20 checks; a free tier covers 20 checks for one person, and the software is open source.
Can you replace Healthchecks.io by building your own?
YES. Replaceable in one session with an AI coding agent. Replacement score 88 out of 100, build time one session. Read what you lose before you decide.
How much does Healthchecks.io cost?
$5 a month on Business — $60 a year. Recorded 14 Aug 2026.
What do you lose by replacing Healthchecks.io?
A scheduler running somewhere your job is not, which is the only place absence can be noticed; Alert routing to email, chat, phone and on-call rotas, already wired; A generous free tier, which makes the money argument thin; Somebody else keeping the thing that watches your jobs running. If any of those carry weight for you, keep paying.
Is there an open-source alternative to Healthchecks.io?
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

