Uptimehub
Blog / Guides 9 min read

Cron Job Monitoring: How to Know When a Scheduled Job Fails

July 2026 · Uptimehub

Live demo 6 regions Read-only checks
ms
timeout
Latency scope · live
Uptime · 30 days
ms
Avg response

Checked from regions with auto-retry. No single-location false alarms.

All systems operational. Steady pulse across every region.

Down · caught in 8s

api.example.com returned no response from all 6 regions. Auto-retry confirmed the outage, then we alerted your team.

Resolved · 4m 12s downtime

api.example.com is back up. The incident is logged to your status page history automatically.

Example, Inc. Status
Operational

90-day uptime · branded · your domain

Live demo · drive it, no signup needed

Cron job monitoring is the practice of confirming that a scheduled job actually ran, finished, and finished on time, instead of assuming it did. It works with a heartbeat: the job sends an HTTP request to a monitoring URL when it completes, and if that request does not arrive inside the window you expect, the monitor alerts you. This catches the failure mode cron itself cannot report, which is a job that never started at all. Standard error handling only tells you about jobs that ran and crashed; a heartbeat check is what tells you about the ones that silently stopped running.

Why cron jobs fail silently

Cron has no idea what your job is supposed to do. It fires a command at a time and moves on. If the command exits with an error, cron will usually mail the output to a local mailbox nobody reads. If the crontab entry got wiped during a deploy, if the server rebooted and the service never came back, if the disk filled up so the interpreter could not start, or if someone commented the line out six weeks ago while debugging, cron reports nothing at all, because from cron's perspective there is nothing to report. Nothing failed. Nothing ran.

That is the real risk with scheduled work. A crashed job at least leaves a stack trace somewhere. A job that quietly stopped running leaves an absence, and absences do not trigger alerts on their own. Teams usually discover these weeks later, when someone asks why the nightly backups have a gap, or why an invoice batch covers a suspiciously short period.

How does cron job monitoring work?

Cron job monitoring uses a heartbeat, sometimes called a dead man's switch. You create a monitor with an expected schedule and a unique URL. At the end of your job, after the work succeeds, the script pings that URL. The monitoring service records the ping and starts a timer. If the next ping does not arrive within the grace period you set, the monitor decides the job failed and alerts you. The logic is inverted from normal monitoring: silence is the alarm, not the all-clear.

Adding it to an existing job is usually one line. A shell job becomes:

0 3 * * * /usr/local/bin/nightly-backup.sh && curl -fsS https://your-monitor-url

The && matters. It means the ping only fires if the script exited successfully, so a job that runs and fails is treated the same as a job that never ran. Both produce no ping, and both alert.

What is a dead man's switch in monitoring?

A dead man's switch is a check that fires an alert when an expected signal stops arriving, rather than when an error is reported. In monitoring terms, your job proves it is alive on every run, and the monitor raises an incident the moment the proof stops coming. It is the only pattern that reliably catches a job which never executed, because it does not depend on the job, the server, or the scheduler being healthy enough to report its own failure. The name comes from the rail industry, where a driver had to keep pressure on a pedal to keep the train moving.

What should you monitor with a heartbeat check

Anything that runs on a schedule and matters if it stops. In practice that means more than the classic nightly cron:

Job typeWhat goes wrong when it stopsSuggested grace period
Database backupsAn unrecoverable gap you find during a restore2 to 4 hours
Billing or invoice batchesRevenue not collected, customers not charged1 hour
ETL and data syncsStale dashboards and wrong numbers in reports30 to 60 minutes
Email digests and notificationsSilent drop in engagement nobody attributes to a bug1 hour
Certificate renewal jobsAn expired certificate takes the site offline1 day
Cache warming and sitemap generationSlow pages, stale search index2 hours
Queue workers and consumersWork piles up unprocessed with no visible error15 to 30 minutes

Set the grace period from the job's real variance, not its ideal runtime. A backup that normally takes 20 minutes but occasionally takes 90 under load needs a window that tolerates 90, or you will train your team to ignore the alerts.

How do you monitor a cron job that runs on a schedule you cannot change?

Wrap it instead of editing it. If the job is managed by another team, or lives inside an application scheduler you do not control, you can still ping from the code path that does the work: at the end of the function, after the commit, send the heartbeat. Laravel's scheduler, systemd timers, Kubernetes CronJobs, GitHub Actions schedules, and Windows Task Scheduler can all issue an HTTP request as a final step. What matters is that the ping happens after success, not before the work starts, otherwise you are monitoring that the job launched rather than that it finished.

Cron monitoring versus uptime monitoring

They answer different questions and you generally want both. Uptime monitoring asks the outside world whether your service responds right now; the monitor initiates the check. Cron monitoring waits for your job to check in; your system initiates the signal. A site can be perfectly up while every scheduled job behind it has been dead for a week, and the reverse happens too, where jobs run fine on a server whose web tier is down. Running cron and heartbeat checks alongside uptime checks covers both halves: the request path your customers use, and the background work they depend on without knowing it.

What to alert on beyond a missed run

A missed ping is the headline, but two other signals are worth wiring up once the basics work. The first is duration. If you ping at the start and again at the end, the monitor can measure runtime and flag a job that finished but took four times longer than usual, which is often the early warning before it eventually times out entirely. The second is exit status. Sending a failure signal on a non-zero exit gives you an immediate alert with the error, rather than waiting out the grace period. For a job in an ETL chain, a late finish matters as much as a missed one, since every downstream table stays stale until it lands, which is why teams running data pipelines usually pair job alerts with something that tracks which downstream tables went stale when an upstream job slipped.

How to set up cron job monitoring

The whole setup takes a few minutes per job.

  1. List every scheduled job you have. Check crontabs on each server, your application scheduler, systemd timers, and any CI schedules. Most teams find jobs nobody remembered.
  2. Rank them by what breaks if they stop. Backups, billing, and anything customers see go first. You do not need to monitor a cache-clearing job on day one.
  3. Create a heartbeat monitor per job with the expected schedule and a grace period based on real observed runtime, not the best case.
  4. Add the ping to the end of the job, guarded so it only fires on success. Use && in shell, or place the request after the last successful step in code.
  5. Deliberately break one job and confirm the alert lands in the channel your team actually watches. An untested alert path is not monitoring, it is a decoration.
  6. Route alerts by severity. A missed backup should reach a person. A missed sitemap regeneration can go to a channel. Alert routing is what decides whether either one gets seen.

Do you need a paid tool for this?

You can build a rough version yourself with a table of last-seen timestamps and a job that checks it, but that solution has the same weakness as a self-hosted monitor: it runs on the infrastructure it is watching. If the server dies, the watcher dies with it and nothing alerts. An external service is checking from outside your failure domain, which is the entire point. The practical answer for most teams is to use a monitor that handles both, so heartbeat checks for your jobs sit in the same dashboard and the same alert routing as the uptime checks for your sites and APIs, instead of paying for and configuring two separate products. Uptimehub counts a heartbeat as an ordinary monitor on a flat per-monitor plan, so watching your jobs does not land on a separate bill.

The short version

Cron will not tell you when a job stops running, because from its point of view nothing happened. Heartbeat monitoring inverts that: your job proves it is alive on each successful run, and silence past the grace period raises the alert. Start with backups and billing, set grace periods from real runtimes, ping only on success, and test that the alert reaches someone. If you already run uptime monitoring for your sites, adding heartbeat checks for the jobs behind them is a small amount of work that closes the gap most teams do not know they have. For a wider view of what to watch and how often, see our guide to choosing check intervals.

Know your site is down before your customers do

Start monitoring your sites, APIs and services from six regions, with alerts by Slack, email, SMS and webhook and a branded status page. Transparent, flat pricing per monitor.