Scheduling health checks with cron

Cron's one-minute floor is too coarse for most health checks. Here's what to use instead, and when cron is fine.

The problem

Cron's finest granularity is once per minute. For an externally-facing service, a one-minute-or-slower check means up to a minute of undetected downtime before anything even starts noticing, and cron itself has no retry, backoff, or alerting. It just runs a script, and turning a failed check into a page is entirely on you.

Purpose-built monitoring (uptime checkers, Healthchecks-style dead-man's-switches, or norc's own run-history view for scheduled jobs) already does sub-minute polling, retries, and alert routing. Reaching for cron here usually means rebuilding a worse version of a tool that already exists.

Use a real monitoring tool for anything user-facing; reserve cron for internal, low-urgency checks.

If a check needs to fire faster than once a minute, or needs retries/backoff/on-call paging when it fails, that's a monitoring product's job, not cron's. A cron-based check script is fine for low-urgency internal signals, such as "did this batch job leave a lock file behind" or "is this internal service still listening", where a delay of a few minutes before anyone notices is acceptable.

Recommended schedule

*/5 * * * *

Every 5 minutes is a reasonable floor for a low-urgency internal check. Anything more time-sensitive than that belongs in dedicated monitoring rather than cron.

Example crontab entry

# norc: healthcheck-internal Check internal queue worker is listening
*/5 * * * * /usr/bin/curl -sf --max-time 5 http://127.0.0.1:9200/healthz || /opt/scripts/alert.sh "worker down"

Failure modes to watch for

  • No --max-time on the check request: a hung endpoint makes the check itself hang, delaying the next scheduled run instead of failing fast.
  • Alerting only on a single failed check with no debounce, paging on a single dropped packet instead of a real outage.
  • The alert script itself has a single point of failure (one SMTP relay, one webhook) with no fallback, so the exact outage that should trigger an alert also takes down the alerting path.
  • Checking that the process is running (`pgrep`) instead of that it's actually serving traffic. A hung-but-alive process passes a liveness check while failing every real request.

How norc helps

For scheduled jobs specifically (not general uptime monitoring), norc flags a run that never happened and keeps run history for what each run returned. Often that is enough without a separate check script. For user-facing uptime, keep a dedicated monitor and use norc for the control side: edit the schedule and see every machine.

Request an invite

Leave your email and we'll send an invite when a spot opens.