GitHub Actions Time Limit, Timeouts and Delays
The GitHub Actions time limit is 6 hours per job on GitHub-hosted runners and 35 days per workflow run, and there are several other limits that look like slowness until you know them. This guide lists the documented limits (checked against GitHub's usage limits page on 2026-10-11), shows how to set shorter timeouts, and then covers the other half of the question: how to delay a job, a step or a whole workflow on purpose. It is related to the slow CI guide.
The limits that matter
| Limit | Value |
|---|---|
| Job execution time, GitHub-hosted runners | 6 hours; the job is terminated and fails |
| Workflow run time | 35 days; the run is cancelled (includes queue and approval time) |
| Job queue time, self-hosted runners | 24 hours, then cancelled |
| Matrix size | 256 jobs per workflow run |
| Workflow runs triggered | 500 per 10 seconds per repository |
| Approvals on environments | A run may wait up to 30 days |
Limits can change, so check GitHub's documentation on usage limits for current numbers. The practical one is the job limit: if a job nears 6 hours, you have a different problem, and sharding or a matrix is the answer.
Set shorter timeouts
The default timeout-minutes for a job is 360, which is the same 6 hours. A hung test then burns six hours of billed time. Set a timeout near twice your normal duration:
jobs:
test:
runs-on: ubuntu-latest
timeout-minutes: 20
steps:
- run: npm ci
- run: npm test
timeout-minutes: 10 # steps can have their own timeout
A timeout fails the job cleanly and stops the bill. Pair it with concurrency to cancel superseded runs (speed-up guide). The workflow YAML checker can flag missing timeouts. If a job regularly hits its timeout, see GitHub Actions slow and slow e2e tests.
How to delay a step
The simplest delay is a shell command:
- name: Wait for deploy to settle
run: sleep 60
This costs billed minutes, so use it sparingly. Better, wait for a condition instead of a fixed time, with a timeout:
- name: Wait for the service
run: |
for i in $(seq 1 30); do
curl -fsS https://staging.example.com/health && exit 0
sleep 10
done
exit 1
How to delay a job
Jobs start when their needs finish. To delay one, add a job that waits and make the next job depend on it. Two approaches that avoid paying for runner time while waiting:
- Environment with a wait timer. In repository settings, create an environment (for example
production) with a wait timer of up to 43,200 minutes (30 days) and optional required reviewers. A job that references it waits without using a runner:
jobs:
deploy:
runs-on: ubuntu-latest
environment: production # wait timer and approvals configured in settings
steps:
- run: ./deploy.sh
Wait timers on environments are available for public repositories, and for private repositories on supported plans, so check your plan.
- Concurrency groups to serialise runs rather than delay them:
concurrency: group: deploymakes the next run wait for the current one.
How to delay a workflow
- Schedule it. Run it at a future time with
on: schedule. Schedules are UTC, and can be delayed under load, especially at the start of an hour; see cron schedules for the syntax and for "schedule not running" problems. The shortest interval is once every 5 minutes. - Dispatch later. Another workflow or an external scheduler can call
workflow_dispatchthrough the API orgh workflow runat the time you choose. - Wait for another workflow. The
workflow_runtrigger starts a workflow when another one completes, which is a delay by dependency rather than by clock.
Unexpected delays that look like limits
- Queued, not running: no free runner, or concurrency limit hit. Self-hosted jobs queue up to 24 hours.
- Cron lateness: scheduled runs can start minutes late during high load.
- Approvals: a run waiting for a reviewer counts toward the 35-day workflow limit.
- Rate-limited actions: third-party APIs return 429 and your retry loop sleeps; set a total timeout.
If many jobs wait for runners, adding capacity or using faster runners cuts the time jobs hold slots. See faster GitHub Actions runners. compiler.dev was faster than GitHub's 2-core runner on 15 of 19 benchmarked stacks, by 1.1 to 3 times, and falls back automatically to your own runners.
Billing note
Delays that occupy a runner, like sleep, are billed as runner minutes at the rates in GitHub Actions pricing explained. Environment wait timers do not hold a runner.
FAQ
What is the GitHub Actions time limit?
6 hours per job on GitHub-hosted runners, and 35 days per workflow run. Set timeout-minutes lower to stop hung jobs early.
How do I delay a GitHub Actions job?
Use an environment with a wait timer, or make the job depend on an earlier job that waits. For short waits, sleep in a step works but uses billed minutes.
How do I delay a workflow?
Schedule it with on: schedule, trigger it later via workflow_dispatch, or chain it with workflow_run.
What happens when a job hits the limit?
The job is terminated and marked as failed. Cache or artifacts produced earlier remain.
Made by compiler.dev. Free tools · Pricing