Estimating and Forecasting CI Costs for a Growing Team
CI cost grows faster than headcount: more developers push more PRs, each PR triggers more runs, and codebases get slower to test. A forecast keeps this from being a surprise on the invoice. This guide gives a model you can build in a spreadsheet in half an hour, with the billing rules that move the numbers.
The model
Monthly CI cost is a product of a few measurable factors:
runs per month = developers x PRs per dev per month x runs per PR (+ main/nightly runs)
minutes per run = sum over jobs of (job minutes, rounded up per job)
billed minutes = runs per month x minutes per run
cost = sum over runner types of (billed minutes x per-minute rate)
minus included free minutes (standard runners only)
Run it separately for each runner type, because rates differ by a factor of ten. The CI minutes forecaster does this arithmetic, and the Actions cost calculator prices the result.
Step 1: Get your real inputs
Do not guess; measure the last 4 to 8 weeks.
Billed minutes by workflow and runner. From the GitHub billing usage report (organization settings, Billing, Usage), export CSV and sum by workflow, SKU and repository.
Runs per PR. The number of workflow runs per pull request, including re-pushes and reruns. A typical value rises with PR size and with flaky tests. Compute it from the API:
gh api "repos/OWNER/REPO/actions/runs?event=pull_request&per_page=100" \
--paginate --jq '.workflow_runs[] | [.head_branch, .run_attempt] | @tsv' | sort | uniq -c | sort -rn | head
Minutes per run. The median and the 90th percentile of billed job time, by workflow.
PRs per developer. Merged PRs per active developer per month, from your repository analytics.
Step 2: Apply the billing rules
These come from GitHub's billing docs and runner pricing page.
- Rounding. Each job is rounded up to the next whole minute. Many short jobs cost more than one longer job with the same total time. A 20 second job bills 1 minute.
- Rates per minute. Linux 2-core $0.006, Windows 2-core $0.010, macOS 3-core $0.062; larger Linux: 4-core $0.012, 8-core $0.022, 16-core $0.042.
- Included minutes. Free: 2,000 per month; Pro and Team: 3,000; Enterprise Cloud: 50,000. They apply to standard hosted runners, not larger runners, and they are consumed at 2x for Windows and 10x for macOS.
- Included minutes are per account, not per developer, so growth erodes them quickly: a Team plan's 3,000 minutes cover about 300 macOS minutes.
Step 3: An example
A team of 15 developers, 20 PRs per developer per month, 3 workflow runs per PR, 12 billed Linux minutes per run, on the Team plan:
runs = 15 x 20 x 3 = 900 runs
billed minutes = 900 x 12 = 10,800 minutes
included = 3,000
chargeable = 7,800 minutes x $0.006 = $46.80 per month
Now add an iOS pipeline: 300 runs a month of 25 macOS minutes: 7,500 minutes x $0.062 = $465, and the free minutes would have covered only a tenth of that. The Mac line item is ten times the Linux one even though it is a third of the runs. The numbers are examples, not benchmarks; replace them with your own.
Step 4: Model growth
Costs do not grow linearly with developers. Include:
- Headcount growth. Developers x PRs per developer.
- Runs per PR growth. Larger teams make more reruns and more review-driven pushes. Assume it climbs unless you invest in stability.
- Minutes per run growth. Test suites and builds grow with the codebase. A 3 percent a month rise doubles minutes in 2 years.
- New workflows. Security scans, end-to-end tests, preview environments and multi-OS matrices each add a line.
- Matrix multiplication. Adding a version or OS multiplies jobs; see matrix builds done right.
- Merge queue runs. An extra run per merge; see GitHub merge queue.
A simple scenario table helps decision-makers:
| Scenario | Developers | Runs per PR | Min per run | Monthly billed minutes |
|---|---|---|---|---|
| Today | 15 | 3 | 12 | 10,800 |
| +6 months, no changes | 25 | 3.3 | 14 | 23,100 |
| +6 months, with fixes | 25 | 2.5 | 9 | 11,250 |
The third row shows the point: reducing minutes per run and runs per PR can absorb a lot of headcount growth. Those are the levers in reducing your Actions bill and speeding up workflows.
Step 5: Count the other costs
Minutes are not everything:
- Storage: artifacts and caches beyond the included quota (cache default 10 GB per repository).
- Larger runners, billed from the first minute.
- Waiting time. Developer time lost to CI wait is usually larger than the CI bill. Use the cost of slow CI calculator: 15 developers waiting an extra 5 minutes on 4 PR runs a day costs far more than the minutes.
- Reruns from flaky tests, which are pure waste. See dealing with flaky tests.
- Self-hosted costs: instances, disks, data transfer, engineer time. See self-hosted vs GitHub-hosted and the AWS tools (EC2, data transfer).
Step 6: Set budgets and alerts
In GitHub billing, create a budget for Actions with an alert at 75 percent and 100 percent. Decide whether it should stop usage at the limit; for production deploy pipelines, alert-only is usually safer. Review the usage report monthly, and tag the top three cost drivers with an owner.
A useful number to track is cost per merged PR (CI spend divided by merged PRs). It falls when you optimize and rises when pipelines bloat, and it normalizes for team size.
Common forecasting errors
- Using average minutes per run when the distribution has a long tail. Use the sum of real usage.
- Forgetting macOS and Windows multipliers on free minutes.
- Forgetting rounding on short jobs and large matrices.
- Assuming the free tier lasts. It is a fixed pool for the whole account.
- Not including scheduled workflows, which run with zero PRs. See cron schedules in GitHub Actions.
FAQ
How much should CI cost per developer?
It varies widely with stack and test depth. Measure your own cost per developer and cost per merged PR, and watch the trend rather than comparing with other companies.
When does it make sense to leave GitHub-hosted runners?
When monthly spend is large enough that the saving beats the engineering effort or the provider's fee. Compare cost per workflow run for the real jobs, as discussed in self-hosted vs GitHub-hosted runners.
Do failed runs count?
Yes, every minute a job runs is billed.
How often should I update the forecast?
Monthly, using the previous month's actuals. A forecast older than a quarter is usually wrong.
Compare with another runner
Once you have a baseline, test the price per run on another provider. compiler.dev's comparison mode runs your existing workflow on faster machines and reports time and cost next to your GitHub-hosted run; in our benchmarks it was faster on 15 of 19 stacks, by 1.1 to 3 times, against GitHub's 2-core runner. Its rates are on the pricing page.
Made by compiler.dev. Free tools · Pricing