If your GitHub Actions bill surprises you, look at the macOS line first. A macOS runner minute bills at roughly ten times a Linux minute, and the xlarge tiers cost more still. One ten-minute macOS job is a hundred Linux-equivalent minutes. Run it on every PR and it is almost certainly the biggest single line on your bill.
The multipliers
- Linux is the baseline (about $0.006/min on a standard 2-core runner in 2026).
- Windows bills roughly 2x Linux.
- macOS bills roughly 10x Linux, and the arm64 xlarge tiers bill above that.
The billing page shows minutes. It does not shout about the multiplier. Ten thousand macOS minutes and ten thousand Linux minutes look the same in a usage table and differ by an order of magnitude in dollars.
How serious projects end up here
Not by accident, exactly. By default-following. vscode's PR pipeline calls its darwin test workflow four times per pull request, each on runs-on: macos-14-xlarge. For an editor that ships a native macOS app, that is a defensible choice made by a team with a Microsoft-sized budget. The pattern to copy is the deliberateness, not the config: most repos running macOS jobs on every PR are not shipping macOS binaries. The job landed in a template years ago and nobody priced it since.
What actually needs macOS
- Xcode builds, iOS/macOS app compilation, simulator tests
- Code signing and notarization
- Reproducing genuinely platform-specific bugs (filesystem case-insensitivity, BSD userland)
What doesn't: your unit tests, your linter, your web build "just to be safe." If the job would pass in a Linux container, it is paying a 10x premium for nothing.
The fixes, cheapest first
1. Move Linux-capable jobs off premium runners. Usually a one-line change:
jobs:
test:
runs-on: ubuntu-latest # was macos-latest — ~10x cheaper
2. Gate macOS to where it earns its rate. Run it on the default branch or a release tag, not every PR commit:
jobs:
macos-test:
if: github.ref == 'refs/heads/main' # PRs run the Linux leg only
runs-on: macos-14
3. Trim the matrix. A full OS x version grid multiplies the premium legs with everything else. And set timeout-minutes everywhere it hurts most: a hung macOS job burns the 6-hour default at 10x the rate.
Find every premium-runner job you have
I built a free scanner for exactly this class of config waste: it flags every workflow using macOS or Windows runners, plus the other quiet defaults (missing timeouts, no concurrency group, uncached dependencies) with copy-paste fixes. Two minutes to find out which of your workflows are on the expensive tier: gitspider.com/scan
This is a syndicated version of the full guide, which also covers the free-plan macOS concurrency cap and per-stack examples.
United States
NORTH AMERICA
Related News
Secret Claude Tracker Shocks Users After Anthropic's Anti-Surveillance Stance
12h ago
EV Batteries Defy Expectations, Last Hundreds of Thousands of Miles
1d ago
GBase 8a Performance Anomaly Case Study: How a Single Parameter Change Sparked a Chain Reaction
1d ago
Who Else Has Inherited a Codebase With Zero Comments and a Prayer?
1d ago
完美的平庸
4h ago