How to Monitor Cron Jobs and Background Workers
Most monitoring tools check whether your services are responding. Send a request, expect a response. But cron jobs and background workers don't respond to anything. They run, do their job, and go quiet. If they stop running, there's no failed request to detect.
This is the problem heartbeat monitoring solves.
What heartbeat monitoring is
Heartbeat monitoring inverts the usual model. Instead of the monitor pinging your service, your job pings the monitor. On each successful run, your cron job sends an HTTP request to a unique URL, called a "heartbeat ping." If the monitor doesn't receive that ping within the expected interval plus a configurable grace period, it fires an alert.
The result: you get alerted when your cron job stops running, not when something downstream breaks because of it.
What it catches that standard monitoring misses
Standard uptime monitoring catches service outages: your API goes down, your database stops accepting connections. Heartbeat monitoring catches execution silences:
- A cron job that was accidentally disabled or deleted.
- A scheduled task that throws an unhandled exception and exits silently.
- A worker that stops processing because a queue backed up and it never recovered.
- A data pipeline that hasn't run since the server was rebooted.
- A billing job that ran but didn't actually complete its work before pinging.
None of these produce a failed HTTP response. They just stop happening. Heartbeat monitoring is the only reliable way to detect them.
How UptimeWarden heartbeat monitoring works
When you create a Heartbeat monitor in UptimeWarden, you get a unique ping URL. Add a single HTTP request at the end of your job (a GET or POST to that URL), and UptimeWarden tracks the timing.
You configure two values:
- Interval: how often your job is supposed to run (e.g., every 15 minutes, every hour, every day).
- Grace period: how much late slack to allow before firing the alert (e.g., 5 minutes for a job that occasionally runs a bit long).
If a ping doesn't arrive within interval + grace, UptimeWarden creates an incident and notifies through your configured channels: email, SMS, Slack, or any of the 9 notification channels available (channel availability varies by plan).
No authentication is required on the ping URL. The URL itself is the secret. For jobs that can't make outbound HTTP calls easily, you can also set up a lightweight script on the same host.
Setting it up
A minimal implementation adds one line to your existing job script:
# At the end of your cron job
curl -fsS https://app.uptimewarden.online/api/heartbeat/<your-token>/ping > /dev/null
For scheduled tasks in application code:
import requests
def run_daily_report():
# ... your job logic ...
generate_report()
send_emails()
# Ping heartbeat on success
requests.get("https://app.uptimewarden.online/api/heartbeat/<your-token>/ping", timeout=5)
The ping should fire only after the job completes successfully. If it fires at the start, you won't detect jobs that start but don't finish.
Grace period vs interval
Setting these correctly avoids false alerts:
- Short jobs (run in seconds): set grace to a few minutes to absorb execution time variance.
- Long-running jobs (take 10 to 30 minutes): set grace to at least 1.5× the typical maximum runtime.
- Jobs with external dependencies (fetch data, write to S3): add buffer for network variance.
If you get an alert on a job that ran fine, the grace period is too short. If your job stops and you don't get an alert for hours, it's too long.
When your job calls a sub-job
If you have a parent job that spawns child tasks (e.g., a pipeline that processes batches), consider a separate heartbeat for each stage. A single end-of-pipeline ping tells you the pipeline completed, but not which stage it failed on. Multiple heartbeats give you more precise failure location.
Beyond cron jobs
Heartbeat monitoring works for anything that should run on a schedule:
- Database backup scripts: know immediately if last night's backup didn't run.
- Log rotation: catch missing rotations before disk fills up.
- Data sync pipelines: detect when an ETL job silently stops fetching.
- Certificate renewal automation: confirm Let's Encrypt renewals complete.
- Health check aggregation scripts: even monitoring infrastructure can be monitored.
The alternative: just checking the output
Some teams skip heartbeat monitoring and instead check the downstream output: query the database to see if the job's records were written, check for a freshly modified file, or monitor a counter that the job increments.
This works, but it's indirect. You're checking a side effect rather than the job itself. It breaks if the side effect changes, requires custom checks per job, and typically means writing the check logic yourself. A heartbeat is simpler and more general.
Getting started
UptimeWarden's Heartbeat monitor is available on all plans including Free. Create a monitor, copy the ping URL, and add one HTTP call to your job script. The whole setup takes under two minutes.
Try UptimeWarden free
Uptime monitoring, incidents and status pages. The Free plan needs no credit card.
Get started