Skip to content
Knowledge base

How to monitor a cron job

Cron jobs, backup scripts, and queue workers don't serve requests, so an HTTP monitor has nothing to check. Practical wrappers for a heartbeat monitor instead: where the ping goes in the script, what a grace period buys you, and the two failure stories a heartbeat catches that an HTTP check never sees.

1. Know why an HTTP monitor can't do this

realuptime.io/kb/heartbeat-check-vs-http-monitor covers the concept: an HTTP monitor works by reaching out to a URL on a schedule, which only makes sense for something that serves requests. A cron job serves nothing, so there is no URL to poll, and the failure that matters, the job silently not running at all, is invisible to any monitor built to reach out rather than wait to be reached.

2. Create the heartbeat and copy the ping URL once

From the dashboard's Add monitor form, set Check type to Heartbeat (cron), name it after the job, and set the expected interval in seconds, the same per-tier floor every check type shares (60 seconds on Free and Growth, 30 on Scale) up to a 24-hour ceiling, plus an optional grace period. Saving reveals the ping URL exactly once: copy it immediately, because like every RealUptime credential it's stored as a hash and can't be shown again. Lost or need to rotate it? Regenerate from the monitor's own detail page; the old URL stops working the moment you do.

3. Put the ping at the end of the script, after the work succeeds

Send a plain GET or POST to the ping URL as the last line of the job, gated on the work actually succeeding: for example `run-backup.sh && curl -fsS "$PING_URL"`, not a ping that fires unconditionally. Both verbs are accepted since the usual caller is curl, wget, or a scheduler's own webhook step, and the response body is discarded either way, so there's nothing to parse.

4. Set a grace period for a job whose runtime varies

The monitor goes down once a ping arrives later than the configured interval plus its grace period, not the instant the interval elapses. A nightly job that normally finishes in ten minutes but occasionally takes forty needs enough grace to absorb that without paging on a normal slow night; without one, grace defaults to zero and the interval alone is the deadline.

5. Know the two failure stories a heartbeat actually catches

Silent death is the case it's built for: the cron entry gets removed, the host reboots and the job never comes back, or the script crashes before reaching the ping line, so no ping arrives and the monitor goes down after interval plus grace. The trap is the opposite mistake, an unconditional ping that fires whether or not the job's own work succeeded: wire the ping after a real success check, or a job that errors out but still executes its last line reports a false all-clear every time, and a heartbeat can only ever tell you a ping did or didn't arrive, never why the code in between passed or failed.

6. Know what happens before the first ping, and after

A heartbeat that has never received a ping reads as awaiting first ping, never down: monitoring only arms on the first ping the token receives, so creating one ahead of deploying the job it watches never pages anyone by accident. Pings are rate limited to 120 requests per minute per token, generous headroom over any correctly configured job, and an unknown or malformed token gets a bare 404 indistinguishable from any other reason, so the endpoint can't be used to test whether a guessed token is real. Heartbeats are available on every plan including Free at no extra cost, and are excluded from uptime percentage figures rather than averaged in, since a push-based check has no polling denominator the way an HTTP monitor does.

Go deeper

The full reference lives in the docs: Heartbeat monitors documentation. Error codes named above are each explained in the error-code reference.