GitHub Actions Windows runner cost per minute
GitHub Actions Windows runner cost per minute is $0.010 for the standard 2-core machine, against $0.006 for the equivalent Linux runner, read from GitHub's runner pricing reference on 21 September 2026. That is a 1.67 times premium rather than the tenfold one macOS carries, which is why Windows rarely dominates a bill on its own and almost always shows up as a matrix leg that nobody has questioned since it was added.

A Windows minute is not expensive enough to be obvious and not cheap enough to ignore. It is the runner type most often bought by default, through an operating system matrix copied from a template, and the cost of that default is small per run and durable across years.
This page states every published Windows rate, prices a worked month against the same work on Linux, and then does the part that actually saves money: separating the jobs that genuinely need Windows from the ones sitting on it out of habit.
The Windows rates, stated exactly
The standard Windows runner, which is what windows-latest gives you, is $0.010 a minute on x64 and also $0.010 on arm64. In a private repository it is a 2 vCPU machine with 8 GB of memory and 14 GB of SSD; in a public repository the standard runners are 4 vCPU with 16 GB and cost nothing.
The larger Windows runners start at 4 cores and $0.022 a minute, then $0.042 at 8, $0.082 at 16, $0.162 at 32, $0.322 at 64 and $0.552 at 96. That top rate is the most expensive minute GitHub sells outside its GPU tier, more than double the 96-core Linux rate of $0.252, and the gap between the two ladders widens at every step.
There is one rate on the Windows card that looks like a mistake and is not. The 2-core Windows arm64 larger runner is $0.008 a minute, which is less than the $0.010 standard Windows runner. It is still a larger runner, so it cannot draw on included minutes and it is billed on public repositories, which is usually enough to cancel the two tenths of a cent on anything but a heavy private pipeline.
| Windows runner | Rate per minute | 8,000 minutes a month | The same work on Linux |
|---|---|---|---|
| Standard 2-core, x64 or arm64 | $0.010 | $80 | $48 at $0.006 |
| Larger 4-core, x64 | $0.022 | $176 | $96 at $0.012 |
| Larger 8-core, x64 | $0.042 | $336 | $176 at $0.022 |
| Larger 16-core, arm64 | $0.050 | $400 | $208 at $0.026 |
| Larger 96-core, x64 | $0.552 | $4,416 | $2,016 at $0.252 |
What the included allowance is worth on Windows
Included minutes are counted in minutes, not in dollars, so where you spend them decides what they are worth. A GitHub Team plan includes 3,000 minutes a month. Spent on standard Linux they cover $18 of compute; spent on standard Windows they cover $30; spent on macOS they cover $186.
That is a free lever most teams never pull. If your pipeline runs both, arrange for the allowance to be consumed by the more expensive runner rather than by whichever workflow happens to run first, because the first 3,000 minutes are identical in cost to you and not identical in value. It is not a large number on a Windows-heavy month, but it is exact and it is free.
The second rule is the one that surprises people on the first invoice after a speed push: included minutes cannot be used for larger runners at all. Moving a Windows job from windows-latest to a 4-core larger runner does not just double the rate, it also removes that job from the allowance, so the marginal change on a small account is larger than the rate table suggests.
Rounding, and why a Windows matrix leg costs more than it runs
GitHub rounds the minutes and partial minutes each job uses up to the nearest whole minute. Windows jobs pay for that more than Linux ones, because the same rounding is applied to a more expensive minute and because Windows runners tend to spend longer in setup before any of your own work starts.
Put numbers on it. A matrix of six Windows jobs that each take 80 seconds uses eight minutes of machine time and bills twelve, because every leg rounds to two. At $0.010 that is $0.12 a run rather than $0.08, half as much again, repeated on every push for as long as the matrix exists. Consolidating those six legs into two longer jobs recovers most of the difference without changing what is tested.
The same arithmetic is why splitting a Windows suite into more shards for speed can cost more than it saves. Each new shard is a new job and a new rounding boundary, so past a certain point you are buying wall clock with billed minutes. Sharding tests across runners has the point where that trade turns.
What actually needs Windows
A short list: .NET Framework, which never left Windows; anything calling Win32 or COM directly; MSI packaging and Authenticode signing; Windows GUI and installer tests; and drivers or services that only exist on the platform. If your product ships a Windows binary that customers run, you need at least one job here and there is no argument to have.
A much longer list does not. Modern .NET builds and tests cross-platform, so a library targeting net8.0 or later is usually verified adequately on Linux with one Windows leg on the default branch rather than on every pull request. JavaScript, Python, Go and Rust test suites that touch no platform API are on Windows because a template put them there. Linting, formatting, dependency audits and documentation builds never need it.
The change is a trigger, not a rewrite: run the full operating system matrix on the default branch and on a schedule, and run Linux alone on pull requests. On the worked month above, moving three quarters of 8,000 Windows minutes to Linux turns $80 into $20 plus $24, which is $36 saved a month for a coverage difference most teams find acceptable. How to reduce GitHub Actions costs prices six more changes on the same basis, and how GitHub Actions pricing works has the model behind the rates.
# before: every push fans out to three operating systems
jobs:
test:
strategy:
matrix:
os: [ubuntu-latest, windows-latest, macos-latest]
runs-on: ${{ matrix.os }}
# after: pull requests get Linux, the full matrix runs where it earns its keep
jobs:
test:
strategy:
matrix:
os: ${{ github.event_name == 'pull_request' && fromJSON('["ubuntu-latest"]') || fromJSON('["ubuntu-latest","windows-latest","macos-latest"]') }}
runs-on: ${{ matrix.os }}
timeout-minutes: 30Where a cheaper runner helps, and where it does not
Be precise about the limit. Latchkey publishes Linux runners only, at $0.0025 a minute for 2 vCPU with 8 GB, so nothing we sell makes a Windows job cheaper. What a cheaper Linux rate changes is the price of everything you move off Windows, which on the worked month above is the larger half of the saving rather than the smaller one.
If Windows itself is the line you need to cut, the market does sell it and we do not, so price the vendors that publish a Windows rate against your own billed minutes rather than against a headline. The honest summary of this page is that Windows is rarely the problem on a GitHub Actions invoice and is frequently a third of it on a matrix nobody has reviewed since it was written.
Start by measuring rather than moving. Identifying high cost GitHub Actions workflows shows how to get minutes broken down by workflow and runner type, which is the only view that separates the Windows lines from the rest.
Key takeaways
- Standard Windows is $0.010 a minute against $0.006 on Linux, a 1.67 times premium rather than a tenfold one.
- The larger Windows ladder ends at $0.552 a minute for 96 cores, more than double the Linux rate at that size.
- Included minutes are counted in minutes, so 3,000 of them are worth $30 on Windows and $18 on Linux.
- Per-minute rounding costs a short Windows matrix leg about half as much again as it actually runs.