← GitHub Actions Minutes Estimator
Doing the math yourself usually means multiplying a job's wall-clock minutes by how often it runs, and stopping there. That gets close on a single small Linux job. It goes wrong in three specific, easy-to-miss ways once a workflow uses a different runner class, a matrix, or a larger runner -- each below with the real arithmetic and a number worked through this tool's own code, not hand-computed.
This tool reads the workflow YAML and applies the same three rules automatically, per job and per matrix leg, so a number it prints has already accounted for all three.
A minute on a macOS runner does not draw one minute from your included allowance -- it draws 10 (Windows draws 2; Linux draws 1). Hand math that just adds up wall-clock minutes treats every runner the same.
Worked example: a macOS job that runs 15 wall-clock minutes a month. Naive math: 15 minutes against the allowance. What actually happens, run through estimate():
RUNNER_CLASSES.macos.multiplier is 10.On a Free plan's 2,000-minute allowance, that one job alone is 7.5% of the month's included minutes -- from something hand math would have logged as a rounding error.
GitHub rounds each job's duration up to the next whole minute, and it does that per job, not per workflow run. Hand math that multiplies total wall-clock time by a rate rounds once, at the end -- which is the wrong place to round when a matrix is involved.
Worked example: a 12-shard test matrix, each shard finishing in 30 seconds. Naive math: 12 × 0.5 = 6 minutes billed. Run through the same estimate() call:
The gap grows with the matrix, not with the job: a 40-shard matrix at 15 seconds each is 10 wall-clock minutes and 40 billed minutes, a 4x gap from the same rounding rule.
A larger GitHub-hosted runner (an -8-cores label, for instance) is billed per minute from the first minute, priced per core, and does not draw from your included allowance at all. Hand math tends to either fold it into the same allowance a standard runner uses, or skip it because "it's free minutes like the rest" -- both read the rule backwards.
Worked example: an 8-core Linux runner, 6 wall-clock minutes per run, 120 runs a month (roughly one push an hour during a working day). Run through estimate():
A workflow using this runner can look free in a spreadsheet that only tracks "minutes against the allowance" -- the allowance column reads zero while the account is actually being charged.
| What hand math usually assumes | What actually happens |
|---|---|
| A minute is a minute, whatever the runner | macOS draws 10x, Windows 2x, against the included allowance |
| Round the total once, at the end | Every job rounds up to a whole minute on its own, before the matrix is summed |
| A larger runner's minutes count the same as a standard runner's | Larger runners bill per core-minute from minute one, outside the included allowance entirely |
Paste a workflow file and get the same three rules applied automatically, per job and per matrix leg, instead of re-deriving them by hand each time.
Free, runs entirely in your browser, nothing is uploaded. Want the arithmetic itself rather than the tool's output? See how GitHub Actions minutes are billed. Already reading your billing page too? See this estimator vs. your billing page.
For a single small job on a Linux runner, hand math gets close enough. It stops working the moment any of three things are true: a job runs on macOS or Windows, a job is part of a matrix, or a job uses a larger runner -- each of those changes the arithmetic in a way that is easy to apply backwards from memory, and this tool exists because getting any one of them wrong understates the real bill by a wide margin.
Treating a larger runner's minutes as if they draw from the same included allowance as a standard runner. They do not -- a larger runner is billed per minute from the first minute, outside the free allowance entirely, which is the opposite of how a standard macOS or Windows job behaves. Getting this backwards is the single easiest way to project a cost of zero for a job that is actually the most expensive one in the file.
GitHub rounds each job's duration up to the next whole minute, and it does that per job, not per workflow run. A matrix of twelve 30-second jobs is 6 minutes of wall-clock work, but it is twelve separate roundings to a full minute each -- 12 billed minutes, double the wall-clock figure. Multiplying total wall-clock time by a single per-minute rate misses this because it rounds once instead of twelve times.
No, and that is the point of it. The OS multipliers, the per-job rounding, and the larger-runner allowance rule are exactly the arithmetic this tool applies to your pasted YAML, so a number it prints has already accounted for the three mistakes on this page without you having to re-derive them by hand.