Webapp monitoring
10 min read
Aug 25, 2026

The Job That Never Ran: Why Cron Failures Are the Hardest Outages to Notice

Nobody gets paged when a cron job doesn't run or there's no error, no crash, just silence. Learn how heartbeat monitoring and the dead man's switch pattern catch scheduled job failures that traditional monitoring can't see.

~ By Meet Sondagar

Nobody gets paged when a cron job doesn't run. There's no error, no crash, no request that fails with a status code. There's just... nothing. A backup that should have happened at 2 a.m. simply didn't, and the first anyone learns about it is three weeks later, trying to restore from a backup that isn't there.

Every monitoring system you've ever used is built around the same core idea: something happens, and you check whether it happened correctly. Cron job monitoring has to work backwards from that. The failure isn't an event to catch it's an event's total absence, and absence doesn't trigger anything on its own.

The Inverted Problem: Monitoring for Nothing

A web request either succeeds or fails, and either way, something happens that a monitor can observe a response, a status code, a timestamp in a log. A cron job that fails to run at all produces none of that. It's not an error. It's an absence, and an absence looks exactly like every other quiet, uneventful moment when nothing was scheduled to happen anyway.

This is the specific challenge behind scheduled job monitoring: you're not checking whether something responded correctly. You're checking whether something happened at all, on a schedule, and the only reliable way to check for "nothing happened" is to expect a signal and notice when it doesn't arrive.

Why This Keeps Happening to Good Teams

Cron failures aren't rare because teams are careless they're common because the failure modes are genuinely invisible from most standard monitoring setups.

  • The job can fail silently inside the script itself. An unhandled exception, a dependency that changed behavior, or a data condition nobody anticipated can cause a script to error out partway through, without that failure ever reaching any external system that would notice.
  • The job can simply never be triggered. A cron daemon restart, a configuration file typo, a deployment that accidentally removed the schedule entry any of these can mean the job was never even attempted, which produces even less of a trace than a job that ran and failed.
  • The job can "succeed" while doing the wrong thing, or nothing at all. A script that exits with a success code after silently failing to process any records looks, from the outside, exactly like a script that processed everything correctly.
  • Traditional monitoring has nothing to check. There's no URL to ping, no server to query, no process actively running most of the time. The gap between runs is the normal state, which makes it structurally difficult to notice when that gap becomes permanent.

Without dedicated cron job monitoring, teams typically discover a missed job the same way they discover most silent failures: downstream. A report that should have generated didn't. A backup that should exist doesn't when you need it. A data sync that quietly stopped days or weeks ago, only noticed when someone finally cross references two systems that have drifted apart.

The Dead Man's Switch: How Heartbeat Monitoring Actually Works

The concept borrows its name from an old mechanical safety idea: a switch that must be actively, continuously held or reset by a person to keep a system running if the person becomes incapacitated and lets go, the switch triggers automatically, precisely because nothing happened when something should have.

Dead man's switch monitoring for cron jobs works the same way. Instead of checking whether the job succeeded by inspecting its output, you flip the entire model: the job itself is responsible for "checking in" sending a small signal (a simple HTTP request, a ping) to a monitoring service every time it runs successfully.

Heartbeat monitoring then does something traditional monitoring can't: it watches for the absence of that expected signal. If the check-in doesn't arrive within the expected window say, the job runs daily but no check in has come in for 26 hours the monitor concludes something is wrong and fires an alert, without ever needing to inspect the job's internal logic at all.

This is a genuinely different monitoring model. You're not asking "did this succeed." You're asking "did this check in when I expected it to," and treating silence itself as the signal.

Setting Up the Check-In

A typical implementation is simple: at the very end of a cron job's script after it has completed its actual work successfully add one line that sends a request to a monitoring endpoint. If the script fails or exits early due to an error, that final line never executes, and the check in never happens, which is exactly the behavior you want: silence on failure, a signal on success.

What to Watch: Signals and Failure Patterns

SignalWhat It Catches
Missing check in within expected windowJob didn't run at all, or crashed before completing
Check in arrives late, consistentlyJob is running slower over time, may be heading toward a timeout failure
Check in arrives, but with an unexpected duration reportedJob completed but took unusually long, worth investigating even without an outright failure
Check in frequency doesn't match expected scheduleJob may be running more or less often than intended, sometimes due to a scheduling misconfiguration
Job reports success but downstream data doesn't reflect itA "successful" run that didn't actually do meaningful work requires validating outcomes, not just execution

Diagnosis: What a Missed Check In Actually Tells You

A missing check in narrows the investigation immediately to a specific window of time and a specific job far better than discovering a problem days later with no timestamp to start from. From there, the diagnostic path is usually: check whether the job was triggered at all (a scheduler/cron daemon issue), and if it was triggered, check the job's own logs for where execution stopped (a script-level failure).

A Practical Production Scenario

A SaaS company runs a nightly job that generates usage reports and syncs billing data to their payment processor. It's been running reliably for over a year, with nobody paying it much active attention, since "it just works."

A routine server migration moves the job to new infrastructure. The migration checklist covers the application and database, but the cron schedule itself configured directly on the old server rather than in version controlled infrastructure code never gets recreated on the new one. The job simply stops existing.

Nothing about this looks like an outage. The application works fine. The website is up. Three weeks later, a customer disputes a charge, and the team discovers the billing sync hasn't run since the migration three weeks of billing data never synced, discovered only because a customer happened to notice a discrepancy.

With cron failure alert monitoring in place even a simple heartbeat check expecting a daily check in this would have surfaced within 24 hours of the missed migration step, not three weeks later through a customer complaint.

Recommended Monitor Setup

  1. Add a heartbeat check in to the end of every critical scheduled job, triggered only after the job's core work completes successfully.
  2. Set the expected check in window slightly wider than the job's normal runtime, to avoid false alerts from ordinary variance, but tight enough to catch a genuine miss quickly.
  3. Monitor check in duration/timing trends, not just presence or absence, to catch a job that's gradually slowing toward a future failure.
  4. Validate meaningful outcomes for critical jobs (like confirming records were actually processed), not just that the script exited successfully.
  5. Keep scheduling configuration in version controlled infrastructure code wherever possible, so a migration or server change can't silently drop a job.

Best Practices for Cron and Background Job Monitoring

Add a heartbeat to every job whose absence would actually matter. Not every scheduled task needs this level of scrutiny, but anything tied to backups, billing, data sync, or customer facing reports absolutely does.

Place the check in at the true end of successful execution, not the start. A check in sent at the beginning of a job only confirms it started, not that it finished which misses exactly the failure mode you're trying to catch.

Set your expected window with enough tolerance for normal variance, but not more. Too tight, and ordinary runtime fluctuation triggers false alerts. Too loose, and a real failure sits unnoticed for longer than necessary.

Validate outcomes, not just execution, for your most critical jobs. A script that exits successfully without actually accomplishing its purpose is a different failure than a crash, and worth checking for separately.

Keep your job scheduling configuration in version control. A cron entry that only exists on a server's local configuration, outside your infrastructure code, is one migration or server rebuild away from silently disappearing.

Assign clear ownership for every monitored job. When a heartbeat alert fires, someone specific needs to know it's their job to investigate an alert with no clear owner tends to get acknowledged and then forgotten.

Common Mistakes

Assuming "no errors in the logs" means the job ran successfully. If the job never ran at all, there are no error logs to check the absence of errors and the absence of execution can look identical from a log only perspective.

Only checking job output after something else already went wrong. Waiting for a downstream symptom (a missing report, a billing discrepancy) means the actual failure happened long before anyone noticed.

Setting the check in window too tight, causing constant false alarms. This leads to the same alert fatigue problem as any noisy monitoring system the team starts ignoring an alert that should matter.

Storing cron configuration outside of version controlled infrastructure. This is one of the most common root causes of a job silently disappearing during a migration, server rebuild, or deployment change.

Not validating that a job actually accomplished its purpose. A successful exit code doesn't guarantee meaningful work happened validate the actual outcome for anything business critical.

Treating every scheduled job with the same level of monitoring rigor. Not everything needs heartbeat monitoring, but skipping it entirely for backups, billing, or data sync jobs is a common and costly oversight.

Start Catching the Jobs That Didn't Run

A cron job that fails to run doesn't announce itself. It just quietly doesn't happen, and the cost of that silence compounds for every day it goes unnoticed.

Start a30 day Statixoup trial and configure heartbeat monitoring for your critical scheduled and background jobs. The next missed run won't wait three weeks to surface you'll know within the hour.

Post a Comment

Frequently Asked Questions

Cron job monitoring is the practice of confirming that scheduled tasks actually run as expected, typically using heartbeat check ins that alert when an expected signal fails to arrive, since a missed or failed cron job produces no error on its own for traditional monitoring to catch.