GitHub Actions timeout-minutes, explained
timeout-minutes tells GitHub Actions how long a job or step may run before GitHub cancels it. If you don't set it, a job can run for 360 minutes, which is six hours.
What timeout-minutes does
The GitHub Actions timeout-minutes setting is a stop watch. You give it a number of minutes. When the time is up, GitHub stops the work and marks it as failed.
Why set one? A stuck job does no useful work. On GitHub-hosted runners it still burns minutes, and it holds a runner. Other jobs may wait in line behind it. A short timeout ends the waste fast and tells you something is wrong.
The default job time limit
A job with no timeout-minutes gets the default: 360 minutes. That is also GitHub's hard GitHub Actions time limit for one job on a GitHub-hosted runner.
Self-hosted runners have a much longer cap. As of November 2026, GitHub lets a job on your own runner run for up to 5 days. A whole workflow run can last up to 35 days. These limits can change, so check GitHub's Actions limits. We list the rest in GitHub Actions limits.
Most jobs need far less than six hours. A test job that takes 8 minutes should not be allowed to run for 360.
Set a timeout on a job or a step
You can set timeout-minutes in two places.
- On a job. The whole job must finish in time, all steps together.
- On a step. Only that one step is timed. This is good for a step that can hang, like a long test run or a download.
A good rule: take your normal run time and double it. If tests take 10 minutes, set 20. It leaves room for a slow day but stops a true hang.
jobs:
test:
runs-on: ubuntu-latest
timeout-minutes: 20 # the whole job
steps:
- uses: actions/checkout@v4
- run: npm ci
timeout-minutes: 5 # just this step
- run: npm test
A step that times out fails the job, unless that step has continue-on-error: true.
You can also use an expression. For example, give pull requests a short timeout and the nightly build a long one. The value must still be a whole number of minutes.
Why jobs hang
A timeout stops the damage. It does not fix the cause. Here are the usual reasons a job hangs:
- A prompt. A tool waits for you to type "y". No one is there. Pass a flag like
-yor--yes. - A stuck test. One test waits on a lock or a server that never answers. Add a per-test timeout in your test tool.
- A network call with no timeout. A download or API call waits forever. Give
curla--max-time. - A service that never starts. A database container never gets healthy, and the job polls it forever.
- A process left running. A dev server or watcher keeps going after the work is done.
To find the step, open the job log on GitHub. The last line before the stop is your clue. Then rerun with debug logs on.
Sometimes the job is not slow at all. It is waiting for a runner, and the clock you see is queue time. Read waiting for a runner. If jobs are just slow, see why GitHub Actions is slow.
Fix the cause, then keep the timeout. It is cheap insurance. The next hang will stop in minutes, and the log will point at the step.
Timeouts on self-hosted runners
timeout-minutes works the same on your own runner. GitHub still cancels the job when time runs out.
What changes is the cost. On GitHub-hosted runners, every minute of a stuck job is billed after your free minutes. On your own machine there is no per-minute charge. A hung job still blocks a runner, though, so set a timeout anyway.
Codemany runs jobs on your own Mac or Linux machine. Each job gets a fresh, single-use runner. If a runner goes offline for 2 minutes, Codemany stops it, along with leftover processes such as simulators, and starts a fresh one. A crashed runner is replaced too. Codemany is $20 a month for 2 machines, however long jobs run. See pricing and how to cut GitHub Actions costs.
Example workflow
This workflow sets a job timeout and a tighter step timeout. It runs on your own machine with one line, runs-on: [self-hosted, codemany].
name: CI
on: [push, pull_request]
jobs:
test:
runs-on: [self-hosted, codemany]
timeout-minutes: 30
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 22
- run: npm ci
timeout-minutes: 10
- name: Unit tests
run: npm test
timeout-minutes: 15
If npm ci hangs, the job fails after 10 minutes, not six hours. You see right away which step stopped.
Questions
What is the default timeout in GitHub Actions?
360 minutes per job on GitHub-hosted runners, unless you set timeout-minutes.
Can I set a timeout on one step?
Yes. timeout-minutes works on a step as well as on a job.
Does a timed-out job still use minutes?
On GitHub-hosted runners, yes. On your own machine there is no per-minute charge.
Related
Read next: GitHub Actions limits, waiting for a runner, slow GitHub Actions, cut GitHub Actions costs and pricing.
Start a 14-day trial No card needed. $20 a month for 2 machines after that.