Skip to content

Guide

Cron job monitoring: catching jobs that silently stop

Cron jobs run backups, send invoices, sync data and clean up. When one stops, nothing breaks loudly. You find out days later, when the data is missing.

Updated 25 October 2026 · By the Upcertain team

Why cron failures go unnoticed

  • cron itself reports nothing. By default output goes to local mail that nobody reads, or nowhere.
  • A job that never starts writes no error. A deleted crontab, a server rebuilt from an old image or a stopped scheduler produces silence.
  • Failures inside the job are easy to swallow. A script that ignores a failed command exits 0 and looks fine.
  • Containers and serverless move the schedule. Jobs scheduled by Kubernetes, a PaaS or GitHub Actions can be paused or skipped by the platform.

Four ways to monitor scheduled jobs

ApproachCatchesMisses
Log or email the outputErrors the job reportsJobs that never start; output nobody reads
Error tracking in the jobExceptions inside the jobJobs that never start
Check the result (a fresh file, a new row)Missing resultsNeeds custom code per job
Heartbeat (dead man's switch)Jobs that do not run or do not finishWrong results from a job that succeeds

Heartbeats are the only approach that catches the commonest failure, the job not running at all, without writing custom checks. Combine them with error tracking for the failures a job can report itself.

How heartbeat monitoring works

The job calls a unique URL when it finishes successfully. The monitor knows how often that should happen. If a call does not arrive within the period plus a grace time, it alerts. In a crontab, it is one extra command after &&:

0 3 * * * /opt/jobs/export.sh && curl -fsS -m 10 --retry 3 https://upcertain.com/api/heartbeat/<token>

Snippets for Node.js, Python, PHP, Laravel and GitHub Actions are in the heartbeat setup guide.

Choosing the period and grace

The period is how often the job should run. The grace covers the normal variation in start time and run time; a nightly export that takes 10 to 40 minutes needs roughly 45 minutes of grace. Start generous, then tighten it after a week of real data. The dead man's switch guide has a table of examples.

Make the job honest

  • Start shell scripts with set -euo pipefail so a failed step fails the script.
  • Send the heartbeat at the end, and only on success.
  • Give the job a timeout, so a hung job stops and the missing heartbeat alerts you.
  • Keep one heartbeat per job, so the alert names the job that stopped.

In Upcertain

Heartbeat monitors take periods from 30 seconds to 30 days and grace up to a day. Missed heartbeats open incidents and alert the same channels as your website monitors, and the next call resolves them.

Questions

Should I send a heartbeat at the start of the job as well?
Usually not. A start ping proves the job began, not that it finished. Send one heartbeat at the end, on success, and rely on the deadline to catch jobs that never start, hang or fail.
What about jobs that run every minute?
Call the heartbeat from each run; Upcertain treats repeated calls within 5 seconds as one, and the shortest period is 30 seconds.