Cron & scheduled jobs

Your nightly job stopped — silently? Catch the cron that fails without telling anyone.

The app looks healthy, the dashboard is up — but the scheduled report stopped arriving, the nightly billing or sync quietly lapsed, and the logs just went blank. Cron failures are invisible by default: nothing pings you when a job doesn’t run. Here is the fast triage list, and the two checks that turn silence into an alert.

why it happens

Nothing alerts you about the job that never ran.

Every other failure throws an error you can catch. A cron that stops just… produces nothing — no log, no exception, no signal. By the time someone notices the missing report, it has been a week and the data gap is permanent. The only reliable way to monitor an absence is a dead-man’s switch: expect a heartbeat on success, and raise an incident when it doesn’t arrive on time.

the checklist

Five ways a scheduled job dies in silence

01

The scheduler itself stopped

Symptom: The report or sync simply stops arriving; the app is otherwise fine.

Fix: Open the scheduler — cron, GitHub Actions schedule, a Bubble recurring event, a Render cron — and confirm the job is still listed and enabled.

02

The job threw, but the error was swallowed

Symptom: The run starts but produces nothing, and no alert fires.

Fix: Read the last run's logs for a caught-and-ignored exception; surface the failure instead of letting the catch block eat it.

03

A deploy removed the job definition

Symptom: Everything worked until a release; the app shipped fine but the schedule is gone.

Fix: Diff the current job definition against the last-known-good version in source control and restore what the deploy dropped.

04

A credential quietly expired

Symptom: The job runs but can't reach its destination, and the failure isn't reported.

Fix: Confirm the API keys, tokens, or service-account credentials the job uses are still valid, and rotate them as a tracked change.

05

The job runs but exits 0 doing nothing

Symptom: The scheduler shows green runs, but the output never actually updates.

Fix: Don't trust the exit code — assert the output artifact (report, log, dashboard) carries a recent timestamp; config drift makes a no-op look like success.

copyable runbook

Paste this into your incident notes

Cron / scheduled-job triage

[ ] Open the scheduler dashboard — is the job still listed AND enabled?
[ ] Read the last run's logs for a swallowed exception.
[ ] Confirm the job's credentials / tokens are still valid.
[ ] Check the output artifact's timestamp — did it actually update?
[ ] Diff the current job definition against last-known-good in source.
[ ] Manually trigger the job; confirm the output marker updates.
[ ] Backfill any runs missed while the job was dead.
[ ] Add a success-only heartbeat + an output-timestamp keyword check.
how to catch it automatically

A dead-man’s switch, plus proof the work was real

Nightlamp watches scheduled jobs two ways. First, a heartbeat dead-man’s switch: the job POSTs to a heartbeat URL only on success, and if no ping arrives within the expected interval plus a grace window, we raise an incident — that is how you alert on a job that never ran. Second, an http_keyword check on the output artifact — the report, log, or dashboard — asserts a recent timestamp marker, catching the job that exits 0 while quietly doing nothing.

Missed success heartbeat
Interval + grace exceeded
Stale output timestamp
Swallowed job errors
Removed job definition
Expired job credentials

Want the silent cron to page you the first night it skips?

Start a trial, give Nightlamp a success heartbeat URL and the job’s output to watch, and we will alert you the first interval a job misses — and the first time it runs but produces nothing — instead of a week later when the data is already gone.

Start 14-day trial · no card