How to Monitor Cron Jobs: A Practical Guide

CronBeacon Team · April 2026

Why monitoring cron jobs matters

Cron jobs run in the background. They don't have users watching them. They don't have dashboards showing their status by default. When a cron job fails or stops running, the only way you'll know is if something downstream breaks — a report doesn't generate, a database backup goes stale, a cleanup job stops clearing old files.

The gap between "job stopped" and "someone noticed" can be hours, days, or weeks. Monitoring closes that gap. It tells you what happened, when it happened, and what to do about it — before the consequences compound.

Approach 1: Log-based monitoring

The simplest approach is to redirect your cron job's output to a log file and check the logs:

0 2 * * * /path/to/backup.sh >> /var/log/backup.log 2>&1

Pros: Simple to set up. No external dependencies. Gives you a local record of what happened.

Cons: Purely reactive. You have to remember to check the logs. If the job doesn't run at all, there's no log entry to find. You need additional log infrastructure (like a log aggregator) to turn logs into alerts.

Log-based monitoring is a good foundation but not sufficient on its own. It tells you what happened when a job ran, but it can't tell you when a job didn't run.

Approach 2: Wrapper scripts

A wrapper script runs your job and captures its exit code, duration, and output. It can then log results, send emails, or write to a status file:

#!/bin/bash
start=$(date +%s)
/path/to/backup.sh
exit_code=$?
duration=$(( $(date +%s) - start ))

if [ $exit_code -ne 0 ]; then
  echo "backup failed (exit $exit_code, ${duration}s)" | \
    mail -s "Cron failure: backup" ops@example.com
fi

Pros: Captures exit codes and timing. Can trigger local alerts like email or Slack notifications.

Cons: Still local to the server. If the server goes down, the wrapper can't run either. You're building monitoring infrastructure yourself — and maintaining it.

Approach 3: Heartbeat monitoring (dead man's switch)

This is the most reliable approach for production cron jobs. Heartbeat monitoring works by inverting the problem: instead of checking whether a job ran, an external service expects to receive a signal from the job — and alerts you when it doesn't.

Here's how it works:

  1. You create a monitor with your job's expected schedule (e.g., 0 2 * * * for "daily at 2 AM").
  2. After your job completes, it sends a check-in (a simple HTTP POST) to the monitoring service.
  3. The service evaluates each scheduled window. If a check-in doesn't arrive within the expected time, it opens an incident and alerts you.

Pros: Detects both failures and missing jobs. Works even when the server is down (because the absence of a signal is the signal). No local infrastructure to maintain.

Cons: Requires an external service. Adds a network call to each job execution.

For production cron jobs, heartbeat monitoring is the recommended approach. It catches the failure mode that logs and wrappers can't: the job that never ran at all.

Setting up heartbeat monitoring with CronBeacon

Here's how to set it up in three steps:

1. Create a monitor with your cron schedule

In CronBeacon, create a new monitor and enter your cron expression (e.g., 0 2 * * *). Not sure about cron syntax? Use our cron expression generator to build and validate it. You'll get a unique ingestion token for this monitor.

2. Add a check-in call to your job

Append a simple HTTP call to the end of your cron job. Here are examples in common languages:

Bash (crontab one-liner)

0 2 * * * /path/to/backup.sh && curl -fsS -X POST \
  https://cronbeacon.dev/api/v1/ingestion/check-in \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"outcome": "success"}'

Python

import requests

# ... your job logic ...

requests.post(
    "https://cronbeacon.dev/api/v1/ingestion/check-in",
    headers={"Authorization": "Bearer YOUR_TOKEN"},
    json={"outcome": "success"},
    timeout=10,
)

Node.js

// ... your job logic ...

await fetch("https://cronbeacon.dev/api/v1/ingestion/check-in", {
  method: "POST",
  headers: {
    "Authorization": "Bearer YOUR_TOKEN",
    "Content-Type": "application/json",
  },
  body: JSON.stringify({ outcome: "success" }),
});

3. CronBeacon alerts you on failures and missing jobs

CronBeacon evaluates each scheduled window. If your job reports a failure, or if no check-in arrives before the deadline, CronBeacon opens an incident and sends you an alert.

Missing vs. failed: why the distinction matters

Most monitoring systems treat all failures the same. But there are actually two very different problems:

  • Failed: Your job ran but reported an error. The code executed, something went wrong (database timeout, API error, out of memory), and the job exited with a failure status.
  • Missing: Your job didn't run at all. No check-in arrived. The cron daemon might be down, the server might have crashed, or the crontab entry might have been deleted.

These require different responses. A failed job might need a code fix. A missing job might need infrastructure investigation. Good monitoring tells you which problem you're dealing with.

For more on preventing these issues, see our guide on what happens when a cron job fails silently. And for general cron hygiene, check out our cron job best practices guide.

Start monitoring your cron jobs today.

CronBeacon detects both failed and missing jobs automatically. Set up monitoring in under a minute.

Start Monitoring Free