Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

GitHub Actions does not guarantee that a scheduled workflow will run exactly on time, or automatically replay a schedule it missed. To recover safely, track each period of work with a durable business key, make processing idempotent, and provide a bounded manual backfill through workflow_dispatch. That way, a rerun can fill a real gap without repeating side effects or skipping an interval.

Why a GitHub Actions cron job may not run

A GitHub Actions schedule is a trigger, not a durable job queue. GitHub says scheduled events can be delayed during periods of high load and queued jobs can be dropped when load is high enough. The start of the hour is especially busy; moving the cron minute later can reduce delay risk, but it cannot guarantee delivery. GitHub documents these schedule limits.

Before treating a gap as a transient platform delay, confirm the workflow is eligible to run. Scheduled workflows run from the latest commit on the repository’s default branch, and the workflow file must be on that branch. Schedules use UTC unless an IANA time zone is specified; the documented minimum interval is once every five minutes. GitHub also describes how a scheduled time affected by spring-forward is advanced. Check the schedule event documentation for the precise behavior.

First distinguish a missing run from a failed run

Look at the Actions page and run history around the expected period. If GitHub created a run and it failed or stopped partway through, a rerun may be appropriate. If there is no run for the period, there is nothing to rerun: create a backfill for the missing business period instead.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

For an existing run, GitHub lets you rerun all jobs, failed jobs, or a specific job. Select the narrowest option only when the earlier steps and their side effects are safe to repeat. Reruns keep the original GITHUB_SHA and GITHUB_REF and use the original triggering actor’s privileges. They are available for up to 30 days after the initial run, with a maximum of 50 reruns per run. See GitHub’s rerun rules.

A rerun re-executes an existing workflow run; it does not represent a new scheduled period. Do not use a run ID or run_attempt as the identity of the work to be performed.

Make the work idempotent by period, not by run

Choose a durable key for each logical unit of work: for example, a calendar date, billing period, data partition, or upstream cursor. Store completion in a durable ledger, such as a database or the system that owns the work. When processing a period, check whether its key is complete, claim or lock it if concurrent processing is possible, perform the work, then record completion after its effects are committed.

Where a downstream service supports idempotency keys, pass the same period key to it on every attempt. A retry for the same period should converge on the same logical result rather than create another charge, report, or other effect. If a process can complete an external side effect and stop before recording the ledger entry, reconcile with the external system or use a transactional or outbox-style design suited to that service. A workflow status alone cannot establish whether an external effect happened.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

The key design distinction is between which period is due and when GitHub happened to start a run. A routine schedule can scan for due periods that are not marked complete. A manual backfill can specify an explicit range or cursor and call the same period-keyed processing logic.

Configure a bounded manual backfill

Add workflow_dispatch to the workflow, then accept explicit inputs such as a start and end period. Validate that the range is well-formed and within an operational limit before processing it. This makes recovery reviewable and prevents a manual run from accidentally processing only the latest period or an unbounded backlog.

GitHub supports dispatch through the Actions UI, CLI, or REST API. The workflow must be configured for workflow_dispatch and its file must be on the default branch. For the REST endpoint, fine-grained tokens need Actions repository write permission. See the dispatch event requirements.

The following is an illustrative workflow shape, not tested copy-and-paste code. The repository must implement period calculation for scheduled runs, input validation, and idempotent processing. Confirm the current syntax for queueing and time zones in GitHub’s workflow syntax reference.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
name: Process periods
on:
  schedule:
    - cron: '17 * * * *'
  workflow_dispatch:
    inputs:
      start_period:
        description: First period to reconcile
        required: true
        type: string
      end_period:
        description: Last period to reconcile
        required: true
        type: string

concurrency:
  group: process-periods
  queue: max

jobs:
  process:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - name: Reconcile due periods
        run: ./scripts/process-periods
        env:
          START_PERIOD: ${{ inputs.start_period }}
          END_PERIOD: ${{ inputs.end_period }}

Adapt the example so scheduled runs determine due-but-incomplete periods without relying on manual inputs. Both trigger paths should call the same reconciliation logic; the dispatch inputs should bound the manual request, not bypass the ledger.

Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Choose concurrency behavior that matches the work

GitHub Actions allows concurrent workflow runs by default. With a concurrency group, GitHub permits one running entity and, by default, one pending run. A new pending run cancels the previous pending run in that group. If every period has a distinct effect, this default can silently discard work waiting to start.

Use queueing when each period must be processed in order, or serialize claims in durable storage so separate runs cannot claim the same period. Queueing does not replace idempotency or a completion ledger. If only the newest desired state matters—for example, rebuilding a cache from current source data—replacing an older pending run may be acceptable. Check GitHub’s concurrency syntax and queueing options.

Recovery runbook for a missed GitHub Actions schedule

  1. Check eligibility: In the Actions page, confirm the workflow is enabled. Verify its file is on the default branch and its on: configuration includes the intended schedule. For a public repository, check for inactivity-related disablement.
  2. Classify the gap: Inspect run history. If a run exists but failed or stopped partway through, decide whether to rerun all jobs, failed jobs, or a specific job. If no run exists, plan a backfill for the missing period.
  3. Verify actual completion: Consult the durable ledger and the system receiving the side effects. Do not infer that work did or did not happen solely from a workflow status.
  4. Dispatch a bounded backfill: Start workflow_dispatch for the missing period or a validated range. Use the same processing code and period key as the normal schedule.
  5. Confirm recovery: Verify completion in both the ledger and downstream system before considering the period recovered.
  6. Reduce avoidable delays: If the schedule runs at minute zero, move it to another minute. Continue reconciling outstanding periods because changing the minute only reduces risk.

Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.