Reliable GitHub Actions Scheduling
Replace GitHub Actions' unreliable cron with precise, on-time triggers via TrigRun and the workflow_dispatch API.
GitHub Actions' built-in cron scheduler is best-effort. Jobs are regularly delayed by 15-30 minutes, and under high load they can be silently dropped. TrigRun calls GitHub's workflow_dispatch API on an exact schedule so your workflows start when you need them to.
The problem
GitHub's own documentation warns:
The schedule event can be delayed during periods of high loads of GitHub Actions workflow runs. High load times include the start of every hour. If the load is sufficiently high enough, some queued jobs may be dropped.
In practice this means:
- 15-30 minute delays are common, especially at the top of every hour
- Scheduled runs can be silently skipped under load
- Self-hosted runners don't help — the queuing happens on GitHub's side
- There is no workaround within GitHub Actions itself
If your workflow needs to run at a specific time — deployments, market-hours automation, report generation, data syncs — this unreliability is a real problem.
The TrigRun solution
Instead of relying on GitHub's cron trigger, use TrigRun to call GitHub's workflow_dispatch API at the exact time you need.
| Setting | Value |
|---|---|
| Template | GitHub Actions Dispatch |
| Method | POST |
| Target | https://api.github.com/repos/{owner}/{repo}/actions/workflows/{workflow}.yml/dispatches |
| Auth | GitHub PAT stored as a TrigRun secret |
| Response | 204 No Content on success |
Step 1: Prepare your GitHub workflow
Add workflow_dispatch as a trigger in your workflow file:
Step 2: Create a GitHub PAT
- Go to GitHub Settings > Developer settings > Fine-grained tokens
- Create a token with Actions: Read and write permission on the target repo
- Store it as a TrigRun secret named
github_pat
Step 3: Create the TrigRun job
Use the GitHub Actions Dispatch template or create directly via API:
That's it. TrigRun fires at exactly midnight UTC. GitHub receives the dispatch and starts the workflow immediately.
Passing workflow inputs
The workflow_dispatch trigger supports custom inputs. Pass them in the request body:
Your workflow accesses them via ${{ github.event.inputs.environment }}.
Common schedules
| Use case | Cron expression | Description |
|---|---|---|
| Nightly build | 0 0 * * * | Every day at midnight UTC |
| Weekday deploys | 0 9 * * 1-5 | 9 AM UTC, weekdays only |
| Hourly smoke tests | 0 * * * * | Every hour on the hour |
| Market open trigger | 30 13 * * 1-5 | 1:30 PM UTC (US market open) |
| Weekly dependency audit | 0 3 * * 1 | Monday 3 AM UTC |
Why not just use GitHub's cron?
| GitHub Actions cron | TrigRun + workflow_dispatch | |
|---|---|---|
| Precision | 15-30 min delay typical | Exact to the second |
| Reliability | Runs can be silently dropped | Retries with exponential backoff |
| Visibility | Check Actions tab manually | Execution history with status, latency, response |
| Notifications | None for missed runs | Slack, Discord, email, webhook on failure |
| Secrets | GitHub secrets only | TrigRun encrypted vault with secret:// syntax |
| Multiple repos | Configure each repo separately | One dashboard for all dispatches |
Expected results
Successful trigger:
| Field | Value |
|---|---|
| Status | 204 No Content |
| Duration | ~300 ms |
| Result | succeeded |
Rate limited (GitHub allows 1,000 API requests/hour):
| Field | Value |
|---|---|
| Status | 429 Too Many Requests |
| Result | Retries with backoff, succeeds on attempt 2 |
Related
- Nightly CI/CD builds — broader CI/CD scheduling patterns
- Job templates — browse all pre-built templates
- Secrets — storing your GitHub PAT securely