Reduce your GitHub Actions costs
Updated
A CI bill is runs, times minutes per run, times the price of a minute. Work on them in that order: a run you avoid saves all of its minutes, a shorter run saves some, and a cheaper minute saves a share of what's left.
Measure first
Find what you're paying for before you change anything:
- Your bill: GitHub's billing pages break usage down by repository and runner.
- Where runs repeat: when you set hushrun up with the GitHub CLI signed in,
npx hushrun initcounts how often CI ran again on code it had already passed in the last 30 days. - What a repeat costs you: the CI waste calculator takes your pushes, pipeline minutes and price, and prints its formula.
Run less often
- Trigger on fewer events. A workflow on both
pushandpull_requestruns twice for every push to a pull request's branch. Why CI runs the same tests twice covers each route. - Cancel superseded runs.
concurrencywithcancel-in-progress: truestops a run when a newer push makes it pointless. - Filter what can't matter.
paths-ignorefor documentation, keeping in mind what happens to required checks. - Skip what already passed.
hushrun runskips a check when this exact code passed it, including on a laptop or in a coding agent's sandbox. See Skip CI when the code hasn't changed.
Make each run shorter
- Cache dependencies.
actions/cache, or the cache option ofactions/setup-nodeand its siblings. GitHub keeps 10 GB per repository by default and evicts what's unused for 7 days. A cache restores files; it doesn't decide whether a job should run. - Fail fast. Run lint and typecheck before the long test suite, so a typo doesn't cost a full run.
- Trim the matrix. Test every version and operating system on
mainor on a schedule, and one combination on pull requests. - Split long test suites. Shards finish sooner but bill the same minutes, or more. Split for feedback, not for the bill.
Pay less per minute
GitHub's per-minute prices for its standard runners, checked in November 2026:
| Runner | Price per minute |
|---|---|
| Linux 1-core, x64 | $0.002 |
| Linux 2-core, arm64 | $0.005 |
| Linux 2-core, x64 | $0.006 |
| Windows 2-core | $0.010 |
| macOS 3-core or 4-core | $0.062 |
- Move what you can to Linux. A job that runs on macOS only by habit costs about ten times as much as on 2-core Linux.
- Use the 1-core runner for light jobs. Lint and other short checks may not need more, at a third of the price.
- Try arm64. It's the cheapest 2-core option, for builds that support it.
- Consider another runner. Third-party runner services and self-hosted machines change the price. They don't change how many minutes your pushes start, so do this after the steps above.
GitHub cut its hosted prices by up to 39% on January 1, 2026. A lower price helps, but coding agents raise the number of runs: see Keep CI useful with coding agents.
An example
Say 20 pushes a working day go to staging and then to production, each starting a 12-minute pipeline on 2-core Linux at $0.006, for 22 working days a month:
20 pushes × 2 branches × 12 minutes × 22 days = 10,560 minutes 10,560 minutes × $0.006 = $63.36 a month
Half of those minutes test files that already passed, so removing the repeats saves half the bill. Moving to arm64 instead would save about a sixth. The calculator runs this with your numbers.