Product
Cron job monitoring that notices the run that never happened
Errors tell you when code throws. They cannot tell you that last night's invoice job never started. A Belvador monitor expects a check-in on a schedule and opens an incident when a run fails, takes too long or does not arrive.
The short answer#
A monitor expects each run of a job and opens an incident when a run fails, runs too long or never arrives.
Report runs with one secret ping URL (no SDK) or with Sentry SDK check-ins.
Ping-URL monitors keep alerting even while your node is down.
Alerts go to your own Telegram, Slack, email or webhook: one message when it breaks, one when it recovers.
Up to 100 monitors per project during the beta, with no per-monitor price.
Two ways to report a run#
| Ping URL | Check-in monitor | |
|---|---|---|
| How the job reports | One HTTP request to a secret URL, from curl, a script or CI | The Sentry SDK (withMonitor, captureCheckIn) or the @belvador/* packages |
| Code changes | None beyond the request | A wrapper around the job |
| Who decides it is late | Belvador's monitor service | Your node |
| While your node is down | Still alerts | Shows Not observable; a real miss is reported late |
Pick the ping URL for shell cron, CI schedules and anything you cannot add an SDK to. Pick check-ins when the job already runs with a Sentry SDK and you want its errors linked to the run.
A ping URL in one line#
# Alive / finished OKcurl -fsS -m 10 --retry 5 -o /dev/null https://ping.belvador.dev/p/bvp_<your-ping-token> || true# Started (optional: arms the max-runtime check)curl -fsS -m 10 --retry 5 -o /dev/null https://ping.belvador.dev/p/bvp_<your-ping-token>/start || true# Failed — alerts at oncecurl -fsS -m 10 --retry 5 -o /dev/null https://ping.belvador.dev/p/bvp_<your-ping-token>/fail || true# Or send the job's exit status right after it: 0 = success, 1–255 = failure./nightly-job.sh; curl -fsS -m 10 --retry 5 -o /dev/null https://ping.belvador.dev/p/bvp_<your-ping-token>/$? || trueThe URL is a secret: anyone who has it can report a run. You can rotate it from the monitor page. Exit codes and short output can be sent too; see ping URL monitors.
A check-in from Node.js#
import * as Sentry from "@sentry/node";await Sentry.withMonitor("nightly-invoices", async () => { // Your job.}, { schedule: { type: "crontab", value: "0 2 * * *" }, timezone: "UTC" });The same pattern exists for Python, TanStack Start, Cloudflare Workers and plain curl (set up a monitor).
Schedules and results#
Cron schedule —
0 2 * * *in the time zone you choose. Clock changes are handled: a 02:30 job on the night the clocks skip 02:30 is due an hour later, at 03:30, and a repeated hour runs once. The cron expression explainer shows the next runs for any expression.Every N minutes or hours — for workers and heartbeats.
When something happens — never late; only failures and timeouts count.
A run ends as OK, Skipped, Failed, Timed out, Missed or Outcome unknown. The last one is for jobs that cannot tell whether their work took effect, such as a payment call that timed out after sending; it asks for review instead of guessing (how monitors work).
Alerts#
The default rule Monitor problems sends one message when a monitor starts failing and one Recovered message when it is healthy again, through your own Telegram bot, Slack webhook, email account or signed webhook. A change from one kind of failure to another does not send a second message (alerts).
Limits#
Up to 100 monitors per project during the beta.
Check-ins come from servers, workers, CI or a shell. Browsers cannot send them.
Belvador does not read your crontab or scheduler. You list the jobs worth watching; nothing is discovered for you.
No on-call rotations or phone calls. Alerts go to the destinations you add.
Questions#
Does it work with Sentry's cron monitoring code?#
Yes. Sentry.withMonitor() and Sentry.captureCheckIn() send check-ins Belvador understands; only the DSN changes (Sentry SDK monitors).
Can a monitor feed an SLO?#
Yes. A monitor or ping URL can be the source of an SLO, counting OK runs against failed and missed ones (SLOs).
Posts on this topic
All posts- Monitoring AI agents that run on serverless functionsAn AI agent on serverless is a chain of short functions with hard time limits. What to monitor at each step, with three lab runs and documented limits.
- Monitoring vibe-coded apps: what breaks after you publishWhat breaks in a vibe-coded app after you publish, why uptime checks still see 200 OK, and the three checks that catch it. Tested on five real failures.
- Cron jobs that never finish: what your heartbeat actually seesWe stopped a cron job with SIGTERM and SIGKILL, three runs each. Where you send the heartbeat decides whether you get a failure, a false OK or silence.
- Ping URLs for shell jobs: the one-liners that report the wrong statusjob; curl, job && curl, pipes, pipefail, set -e: what each one-liner sends to a heartbeat ping URL when the job fails, and when the ping itself fails.
Try it on your own Hetzner project
Free during the beta. Hetzner bills the server; Belvador never bills per event.