What a self-hosted GitHub runner really costs
Self-hosted GitHub runner cost is not a line on your GitHub invoice: GitHub's billing documentation still states that Actions usage is free for self-hosted runners, and the $0.002 a minute platform charge announced for 1 March 2026 was postponed before it took effect. What you pay instead is compute by the hour rather than by the job minute, plus the engineering time the fleet consumes, and the second one is what decides whether self-hosting was cheaper.

The honest version of this comparison is a break-even, not a verdict. A GitHub-hosted standard Linux runner costs $0.006 a minute, which is $0.36 for an hour of job time, billed only while a job runs. Your own instance costs whatever it costs every hour it is switched on, whether or not a job is running on it.
So the whole question is utilization, and after that it is ops. This page does the first part with published numbers and hands you the inputs for the second, because nobody can tell you what an hour of your team's time is worth.
What GitHub charges today: nothing
GitHub's billing documentation is unambiguous: Actions usage is free for self-hosted runners. No orchestration fee, no per-job fee, no queue fee. You register a runner, it takes jobs, and none of it reaches the invoice.
That was very nearly not true. On 16 December 2025 GitHub announced a $0.002 per minute Actions cloud platform charge on self-hosted usage in private repositories from 1 March 2026, alongside a cut of up to 39 percent in hosted prices on 1 January. The price cut happened. The charge did not: GitHub postponed it "to take time to re-evaluate our approach", and it has not returned.
Plan for the published number, which is zero, and know the size of the drafted one: at $0.002 a minute, 100,000 self-hosted minutes a month would have carried $200 before a single instance was paid for.
The number you are trying to beat
A standard GitHub-hosted Linux x64 runner is $0.006 a minute, or $0.36 per hour of job time, and GitHub bills only the minutes your jobs actually run, rounded up to the whole minute per job. Private repositories get 2,000 to 50,000 included minutes a month depending on plan, which come off the top.
Notice the shape of that bill. It is elastic: a quiet week costs nothing, and you never pay for a machine that is waiting. A self-hosted fleet inverts that. You pay for the waiting, and the jobs are free.
What a self-hosted fleet actually costs
The instance bill is the obvious part and rarely the largest one. The parts that get left out of the spreadsheet are the ones that make a self-hosted fleet look cheaper than it is.
Idle time is the biggest of them. CI load is bursty, so a fleet sized for the Tuesday afternoon peak is mostly idle at 4am, and your cloud provider bills an idle hour at the same rate as a busy one.
- Compute, billed by the wall-clock hour the instance exists, not by the job minute.
- Idle capacity: the gap between the fleet you sized and the jobs that arrived.
- Storage and egress: runner images, caches, container layers pulled on every cold runner.
- Image maintenance: the toolchains GitHub-hosted images ship with are now yours to build and patch.
- Operations: scaling, upgrades, stuck runners, full disks, and the pager that goes with them.
- Security: an ephemeral runner per job is a design decision you now have to implement, not a default you inherit.
# The workflow side of self-hosting is one line. Everything above is the other side.
jobs:
build:
runs-on: [self-hosted, linux, x64, ci-pool]
timeout-minutes: 30
steps:
- uses: actions/checkout@v7
- run: make testThe break-even, in one line of arithmetic
An hour of job time costs $0.36 on a standard hosted Linux runner. Your fleet delivers an hour of job time for its hourly instance price divided by its utilization, because at 25 percent utilization the fleet has been switched on for four hours to deliver one hour of work.
So the break-even instance price is $0.36 multiplied by your utilization. At a genuinely saturated 100 percent, an instance may cost up to $0.36 an hour and still be cheaper. At 50 percent, $0.18. At 25 percent, which is a realistic figure for a fleet that also has to absorb peaks, $0.09. At 10 percent, $0.036, which is below the price of almost anything with a CPU in it.
That ceiling is before storage, before egress, and before a single hour of anyone's time. If the postponed $0.002 platform charge ever arrives, every ceiling in that list falls by a third, because the budget to beat drops from $0.006 a minute to $0.004.
githubConfigUrl: https://github.com/your-org
githubConfigSecret: arc-github-app
runnerScaleSetName: ci-pool
# minRunners is the dial this whole page is about: every warm runner is an hour
# you pay for whether a job arrives or not, and every cold start is a queue.
minRunners: 0
maxRunners: 20| Fleet utilization | Break-even instance price per hour | If the $0.002 charge returns |
|---|---|---|
| 100% | $0.360 | $0.240 |
| 50% | $0.180 | $0.120 |
| 25% | $0.090 | $0.060 |
| 10% | $0.036 | $0.024 |
A worked example, with the inputs written down
Take 100,000 private-repository Linux minutes a month, which is 1,667 hours of job time. On standard hosted runners that is $600, less whatever your included minutes cover: $582 on a Team plan, $300 on Enterprise Cloud.
To beat $600, the entire self-hosted fleet has to come in under $600 a month. At 25 percent utilization the fleet is switched on for 6,667 instance-hours to deliver those 1,667 hours of work, so the instances must average less than $0.09 an hour. Every hour of engineering time you spend on the fleet comes out of the same $600: at a loaded cost of $100 an hour, six hours a month is $600, which is the entire budget.
Run the same numbers at 60 percent utilization and the ceiling rises to $0.216 an instance-hour, which is where a well-packed fleet of committed-spend instances starts to look genuinely cheap. The variable that decides this comparison is not the instance price list. It is how much of the month your runners are actually working.
When self-hosting wins, and when it does not
Self-hosting wins when the machine is the point. GPU builds, Apple silicon at a scale GitHub does not sell, hundreds of gigabytes of disk, or jobs that must sit inside your VPC next to the data they test against: in those cases a hosted runner is not what you need at any price. It also wins at high, sustained utilization on committed cloud spend.
It loses on bursty, low-utilization workloads, on small teams where ops hours are a large share of the total, and on Windows or macOS fleets where the machines are expensive and the tooling is worse. It also loses quietly, which is the dangerous case: the invoice arrives at the cloud provider, not at GitHub, so nobody compares the two.
A managed runner is the third option and it is priced like the first: Latchkey publishes $0.0025 a minute at 2 vCPU, billed per job minute with no fleet to keep warm, which puts an hour of job time at $0.15 against the $0.36 hosted rate. That is the comparison to run before you decide the only way down from $0.006 is your own hardware, and how Latchkey cuts the GitHub Actions bill is the case for it.
How to compare without fooling yourself
Price engineering hours, not just instances. A fleet that saves $200 of compute and costs an engineer a day a month has saved nothing. Put the hours in the same spreadsheet as the instance bill, at your real loaded hourly cost.
Count the re-runs on both sides. A job that dies because a runner ran out of disk is minutes paid for nothing, and self-hosted runners fill up in ways hosted ones do not, because the disk is yours and it persists. Freeing disk space on GitHub Actions runners measures what a cleanup actually reclaims.
Then check the assumption underneath the whole exercise. If the reason you are self-hosting is the per-minute rate, compare that rate against every option before you take on a fleet: how GitHub Actions pricing works has the published numbers, the GitHub Actions cost calculator prices your own month, and macOS runner cost covers the one platform where the rate really is the problem.
Key takeaways
- GitHub charges nothing for self-hosted runners today, and the $0.002 a minute charge announced for March 2026 was postponed.
- Hosted bills job minutes, self-hosted bills wall-clock hours, so utilization decides the comparison.
- Break-even instance price is $0.36 an hour at full utilization and $0.09 at 25 percent, before any ops time.
- Put engineering hours in the same spreadsheet as the instance bill or the comparison is not a comparison.
Frequently asked questions
Per minute charges for self hosted runners?
Is GitHub Actions free for self-hosted runners?
When do self-hosted runners actually cost less than GitHub-hosted?
Is the GitHub Actions control plane no longer free?
Related guides
References
- GitHub Actions billing: Actions usage is free for self-hosted runners (verified 2026-09-20)
- GitHub Changelog: update to GitHub Actions pricing and the postponed self-hosted charge (verified 2026-09-20)
- GitHub: Actions runner pricing, every per-minute rate by runner (verified 2026-09-20)
- actions-runner-controller: gha-runner-scale-set chart values (verified 2026-09-20)
- Latchkey pricing: published per-minute runner rates (verified 2026-09-20)
- GitHub Actions documentation