MonitoringBeginner

Cron Job Monitoring: The Complete Guide (2026)

Cron jobs fail silently, with no request to alert on. Learn how heartbeat monitoring catches missed and late cron runs, and how to set it up.

ObserveOne Team
6 min read

A cron job that stops running doesn't throw an error. It just stops. There's no failed request, no 500 status code, no dashboard turning red — the backup script, the report generator, the cleanup task simply doesn't run tonight, and nothing about that is visible from the outside. Cron job monitoring exists to close that gap.

What Is Cron Job Monitoring?#

Cron job monitoring confirms that a scheduled task — a cron job, a Kubernetes CronJob, a Windows Task Scheduler entry, a queued background worker — actually executed, executed on time, and finished without error. It's a different problem from monitoring a website or an API, because there's no request coming in to check against.

Standard uptime monitoring works by sending a request and grading the response: is the server up, did it answer within the timeout, did it return the right status code. That model assumes something is always listening. A cron job isn't listening for anything. It wakes up on a schedule, does its work, and exits. There's nothing to poll in between runs, and nothing to poll if a run silently never happens.

Why Status Checks Don't Work for Cron#

If you try to monitor a cron job the same way you'd monitor a website, you run into the core mismatch immediately: a cron job that fails to run produces zero signal. No 500, no timeout, no connection refused. The absence of an event is the failure, and a monitor built to check for the presence of a bad response has nothing to grab onto.

This is why cron monitoring uses the opposite direction of check.

How Heartbeat Monitoring Works#

A heartbeat check (also called a dead man's switch) flips who initiates the request. Instead of a monitoring service reaching out to your job, your job reaches out to the monitoring service:

1. Cron job runs, does its work
2. Job finishes successfully
3. Job sends a GET or POST to a unique heartbeat URL
4. Monitoring service resets a timer for that heartbeat

The check is defined by two numbers:

  • Period — how often the job is expected to run (daily, hourly, every 15 minutes).
  • Grace — how much lateness is tolerated before it's treated as a failure, to absorb normal variance in run time.

If the next ping doesn't arrive within period + grace, the monitor flips to overdue and fires an alert. No port has to be opened, no credentials handed to the monitoring service, and no outbound access from the monitor into your infrastructure — the job reports out on its own schedule, which is also why heartbeat checks work equally well for jobs running behind a firewall, on a laptop, or inside a Kubernetes cluster with no public ingress.

What Cron Monitoring Should Catch#

The job never ran. The most common failure: a crashed host, a disabled crontab entry, a Kubernetes CronJob stuck in a bad state, a deploy that silently dropped the schedule.

The job ran late. Resource contention, a slow dependency, or a queue backup delays the run past its grace window — worth knowing even if it eventually completes.

The job ran but errored out. This only gets caught if the heartbeat ping sits at the end of the script's success path, not the start. A ping placed before the job's logic runs fires regardless of whether the job actually succeeds, which silently defeats the monitor. Put the ping last, after the work is confirmed done, so a script that throws partway through never sends it — and gets flagged exactly like a job that never ran at all.

Setting Up Cron Job Monitoring#

1. Create the heartbeat check with a name, a period matching the job's schedule, and a grace window sized to the job's normal runtime variance, not just its average.

2. Get a unique ping URL from the monitoring platform. With ObserveOne's CLI:

obs heartbeat create --name "Daily Backup" --period 86400 --grace 3600

This creates a daily heartbeat with a one-hour grace window. Creating it returns a unique ping URL for that check.

3. Add the ping as the last line of the job, after its success logic, not before:

#!/bin/bash
./run-backup.sh && curl -fsS "$HEARTBEAT_PING_URL"

The && matters — the ping only fires if run-backup.sh exits cleanly.

4. Route the alert. Background jobs (log rotation, cache warming) can go to a Slack channel. Anything customer-facing (billing runs, data exports) should page on-call the same way a site-down alert would.

5. Mute during planned changes. Pausing or muting the heartbeat before a deploy, a manual re-run, or a schedule change stops the fix itself from triggering the alert it exists to prevent:

obs heartbeat toggle-muted <id> # mute alerts without pausing the timer
obs heartbeat reset <id> # reset the timer after a manual run

Kubernetes CronJobs#

The same mismatch applies to Kubernetes CronJobs, with an extra failure mode on top: a CronJob can silently stop scheduling Job objects entirely if it hits startingDeadlineSeconds or gets stuck in a Suspend: true state after a botched change, and kubectl get cronjobs won't page anyone about it. A heartbeat ping added to the pod's entrypoint, sent only after the container's main process exits 0, catches both the "never scheduled" and the "scheduled but the container crashed" cases with one check.

Cron Monitoring vs. Uptime Monitoring#

Uptime monitoringCron job monitoring
Who initiates the checkMonitor polls your serviceYour job pings the monitor
What triggers an alertBad response, timeoutNo ping within period + grace
Works behind a firewallNo (needs inbound access)Yes (job only needs outbound)
CatchesServer down, slow, wrong contentJob never ran, ran late, exited with an error

Most teams need both: uptime checks for anything that serves a request, heartbeat checks for anything that runs on a schedule and doesn't.

Conclusion#

A cron job's failure mode is silence, not an error page, which is exactly what makes it easy to miss for weeks. Heartbeat monitoring closes that gap by flipping the check around: instead of asking "did the server answer," it asks "did the job report in on time," and pages you the moment it doesn't.

ObserveOne's heartbeat checks sit alongside HTTP, TCP, database, and SSL monitoring in one dashboard, with period and grace configurable per job through the CLI or the API. Build the schedule first with the free cron expression parser, then wire a heartbeat to it so a broken schedule and a broken run both get caught the same way.

Frequently Asked Questions

Cron job monitoring is the practice of confirming that a scheduled background task actually ran, ran on time, and finished without error. Unlike monitoring a website, there's no incoming request to check: the job runs on its own schedule, often with nobody watching, so a missed or silently broken run can go unnoticed for days.

The most common method is a heartbeat check, also called a dead man's switch: the cron job sends a ping to a monitoring URL right after it finishes. The monitoring service expects a ping within a set period plus a grace window. If the ping doesn't arrive in time, it marks the job overdue and alerts you. Nothing has to reach into your infrastructure or hold credentials, since the job reports out instead of being polled.

Uptime monitoring sends a request to a server and checks the response, which works because a website is always supposed to be reachable. A cron job isn't reachable in that sense: it runs, does its work, and exits. Cron monitoring flips the direction, waiting for the job to report in rather than polling it, which is why it needs a heartbeat check instead of an HTTP check.

Only if the ping is placed after the job's success logic, not at the start. A heartbeat placed at the top of the script fires whether the job succeeds or crashes, which defeats the point. Placing it as the last line, after the work is confirmed done, means a script that errors out partway through never sends the ping, and gets caught as overdue just like a job that never ran.

Most monitoring platforms, including ObserveOne, include heartbeat checks on their free tier alongside HTTP and uptime monitoring, usually capped by the number of monitors or check frequency. Paid tiers typically add shorter grace windows, more monitors, and richer alert routing.

Ready for AI-Powered Testing?

ObserveOne monitors your selectors 24/7 and automatically heals them when websites change. Never deal with broken tests again.

Start Free Trial