Skip to content
Latchkey

Scheduled cron runs late (timing is not guaranteed) in CI

GitHub Actions does not guarantee exact schedule timing. The schedule event can be delayed during periods of high load, and runs at the top of the hour (minute 0) are most likely to queue late. Do not rely on cron for second-accurate timing.

What this error means

A cron set for 0 * * * * fires several minutes past the hour, sometimes 10 to 30 minutes late, and the delay is worst at peak times like midnight UTC.

GitHub Actions
# cron: '0 * * * *'  expected 12:00:00 UTC
# actual run started 12:14 UTC during peak load

Common causes

Schedule dispatch is best-effort under load

GitHub queues scheduled events and dispatches them as capacity allows, so heavy load pushes start times later.

Top-of-hour crowding

Many workflows use minute 0, so 0 * * * * competes with everyone else and is most likely to be delayed.

How to fix it

Avoid the top of the hour

  1. Pick an off-peak minute like 17 or 43 instead of 0.
  2. Spread multiple jobs across different minutes.
  3. Do not depend on exact start times for correctness.
.github/workflows/nightly.yml
on:
  schedule:
    - cron: '17 3 * * *'   # less crowded than '0 3 * * *'

Design jobs to tolerate delay

Make the job idempotent and time-independent so a late start does not break correctness. For strict timing, trigger from an external scheduler via workflow_dispatch or the API.

How to prevent it

  • Never assume second- or minute-accurate scheduling.
  • Use off-peak minutes and stagger jobs.
  • For strict timing, drive runs from an external scheduler.

Frequently asked questions

What causes "schedule delayed under load"?
GitHub queues scheduled events and dispatches them as capacity allows, so heavy load pushes start times later.
How do I fix schedule delayed under load?
Avoid the top of the hour

Related guides

References

Latchkey auto-heals failures like this one - detected, fixed, and retried without you. Start free → 30-day trial · No credit card