Skip to content
← Guides

Your GitHub Actions cron didn't run. Get told next time.

The schedule trigger is best-effort and silent. A three-line heartbeat makes it accountable.

Why scheduled workflows don't run

  • Delays and drops at busy times. GitHub documents that scheduled events can be delayed during periods of high load, and some queued runs may be dropped. Top-of-the-hour schedules are the most affected.
  • Auto-disabled after 60 days. In public repositories, scheduled workflows are disabled automatically when there's been no repository activity for 60 days.
  • Default branch only. Schedules run from the default branch; a workflow edited on another branch never fires.
  • The job runs but produces nothing — an empty export, a skipped step, a continue-on-error that hid a failure.

Add a heartbeat step

Add curl steps that ping /start first, the ping URL on success() and /fail on failure(). Create a Did It Run? watch with the same cron expression in UTC and a grace window of 30–60 minutes to absorb GitHub's normal delays.

Check the output, not just the exit code

Send your job's output file as the ping body (--data-binary @output.txt) and set a minimum size or required keyword. A green run with an empty report raises an empty alert.

Tip: avoid the top of the hour

Schedule at an odd minute (e.g. 17 6 * * *) — it's less congested — and mirror it on the watch.

FAQ

Should I keep the ping URL secret?

Yes. Store it as a repository or organization secret and reference it as ${{ secrets.HEARTBEAT_URL }}.

What grace period should I use?

30 minutes is a sensible start for GitHub schedules; increase it if you see occasional late runs.

Can one watch cover a matrix of jobs?

Use one watch per job you care about, or ping once from a final job that depends on all the others.

Know the next time it doesn't run

Know when your AI agents and automations didn't run. Free for 3 watches.

Start free