GitHub Actions minutes and billing, explained
GitHub Actions minutes are metered per job rather than per workflow run, and each job is rounded up to the whole minute before it reaches the invoice, so a fan-out of short jobs bills far more than a stopwatch would say. This page follows one month through that meter: what the clock counts, which billing SKU each runner label maps to, what the included minutes in your plan do and do not cover, and which columns of the usage report carry the answer.

The rate card is the easy half of an Actions bill and the half everyone reads. The hard half is the counting: the unit is a job, the rounding happens before anything is multiplied, and the number you are charged for is already larger than the number your runs page shows you.
The unit is a job, and the clock is execution time
GitHub meters the execution time of each job on a GitHub-hosted runner and then, in the words of its pricing reference, "rounds the minutes and partial minutes each job uses up to the nearest whole minute". Two things follow from that sentence and most surprises come from one of them.
First, the rounding happens per job, not per run and not per month. A workflow of eleven jobs is eleven separate roundings, so the cost of splitting work into more jobs is paid up front in whole minutes whatever the wall clock does.
Second, the clock is execution time. GitHub's limits reference treats waiting and running as different things: a job may run for up to six hours of execution time on a hosted runner, while a job on a self-hosted runner "can be in the queue for 24 hours before it is automatically cancelled". The minutes that reach your bill are the ones a runner spent working on the job, and the usage charged is charged "to the repository owner, not the person who triggered the workflow runs".
Rounding is a tax on short jobs, and it is bigger than it looks
Take one matrix of 20 jobs and vary only how long each leg takes. The minutes used are the stopwatch; the minutes billed are what the rounding rule produces; the cost is the billed column at the $0.006 standard Linux rate.
A 61 second job bills two minutes. Twenty of them use 20.3 minutes of machine time and bill 40, which is 97 percent more than the work took. At 25 seconds a leg it is 140 percent more, at three minutes and one second 33 percent, and at nine and a half minutes 5 percent. The tax is not a fixed percentage, it is a fixed amount of waste per job, so it lands hardest exactly where teams have been told to optimize: more parallelism, shorter jobs.
The reading is not "never parallelize". A matrix leg under a minute is nearly free to run and never free to bill, so collapsing trivial legs into real ones is a saving you can compute before you make it.
| Each of 20 jobs takes | Minutes used | Minutes billed | Billed at $0.006 |
|---|---|---|---|
| 25 seconds | 8.3 | 20 | $0.12 |
| 61 seconds | 20.3 | 40 | $0.24 |
| 3 minutes 1 second | 60.3 | 80 | $0.48 |
| 9 minutes 30 seconds | 190.0 | 200 | $1.20 |
Every runner label bills as a named SKU
The label you type in runs-on picks a machine, and the machine has a billing SKU. That SKU is the string that appears on the usage report, so it is the join between a workflow file and a line on an invoice. Knowing it turns "where did the money go" into a spreadsheet filter.
The larger runners follow the same scheme with their core count in the name, from linux_4_core at $0.012 a minute to linux_96_core at $0.252, and the two larger macOS machines are macos_l at $0.077 and macos_xl at $0.102. The rates and the rules behind them are on how GitHub Actions pricing works.
| What you type in runs-on | Billing SKU on the report | Per-minute rate |
|---|---|---|
ubuntu-slim | actions_linux_slim | $0.002 |
ubuntu-latest | actions_linux | $0.006 |
ubuntu-24.04-arm | actions_linux_arm | $0.005 |
windows-latest | actions_windows | $0.010 |
windows-11-arm | actions_windows_arm | $0.010 |
macos-latest | actions_macos | $0.062 |
What the included minutes cover, and the four things they do not
Your plan comes with a monthly quantity of minutes for standard GitHub-hosted runners in private repositories, and that quantity resets at the start of each billing cycle. It is stated in minutes rather than in dollars, and GitHub publishes no per-operating-system conversion for those minutes, so read the allowance as a minute count rather than as an amount of money.
Everything else is outside it, and each of the four exclusions below has caught somebody. The last one is the friendliest: self-hosted usage is not metered at all, so it neither costs money nor eats the allowance.
- Larger runners: "Included minutes cannot be used for larger runners", so a job that moves up a size starts billing from its first minute.
- Storage: artifacts and Packages share one allowance and the Actions cache has its own, each with its own per-GB rate, measured hourly rather than monthly.
- Public repositories: standard runners there are free and unlimited, so they never touch the allowance in the first place.
- Self-hosted runners: "GitHub Actions usage is free for self-hosted runners", so those minutes are not metered and draw nothing from the quota.
Where the bill actually appears
The dashboard shows totals. The usage report shows lines, and lines are what you need. GitHub publishes three of them: a summarized report covering up to a year, a detailed report covering at most 31 days, and an AI usage report. The detailed one is the only one that names the workflow, and reports arrive by email to the address on your account rather than downloading in the browser.
Six columns carry an Actions answer. Read sku first, because it tells you which machine ran the work, and workflow_path second, because it tells you which file asked for it. The pairing of those two is what separates a Linux job that costs a tenth of a cent from a macOS job in the same repository.
| Report column | What it holds on an Actions line |
|---|---|
sku | The runner SKU that ran the job, for example actions_linux or linux_16_core |
quantity and unit_type | Billed minutes, already rounded up job by job |
applied_cost_per_quantity | The per-minute rate that line was charged at |
discount_amount | Free usage priced then discounted, which is how public-repo and self-hosted minutes appear |
workflow_path | The workflow file that produced the usage, in the detailed report only |
net_amount | What that line actually adds to the invoice |
One month, counted the way the meter counts it
Take a private repository that runs 250 workflow runs a month. Each run is a 12 leg test matrix at 3 minutes 20 seconds a leg, plus one build job of 6 minutes 30 seconds. Every leg rounds to 4 minutes and the build job rounds to 7, so a run bills 55 minutes and uses 46.5.
Across 250 runs that is 13,750 billed minutes against 11,625 used, an overhead of 2,125 minutes or 18.3 percent. At the standard Linux rate of $0.006 the month is $82.50, where the stopwatch figure would have been $69.75: the rounding alone is $12.75. On a GitHub Team plan the first 3,000 minutes are included, so the invoice is 10,750 minutes at $0.006, which is $64.50.
Now price the same 13,750 billed minutes on a Latchkey small runner at the published $0.0025 a minute. The compute line is $34.38, and on top of it sits the monthly plan fee, which is $5 on Developer, $19 on Launch and $49 on Scale. Latchkey's own included minutes, 2,000 to 6,000 a month depending on plan, are not netted off here. So the all-in month is $39.38, $53.38 or $83.38 against GitHub's $64.50: lower on the two smaller plans, higher on Scale unless you are using the 6,000 minutes that plan prepays. That is the shape of every honest comparison at this volume, and how Latchkey cuts the GitHub Actions bill is the case for the volumes where the gap widens.
Whichever way that lands, the 2,125 rounded-up minutes are waste on both price lists. Consolidating the 12 legs into 6 legs of about 6 minutes 40 seconds bills 42 minutes for the legs instead of 48, so a run falls from 55 billed minutes to 49. That is 1,500 minutes a month, or $9.00, for exactly the same tests.
Key takeaways
- The billing unit is a job, so every job in a workflow is rounded up to a whole minute separately.
- A 61 second job bills two minutes: 20 of them bill 40 minutes for 20.3 minutes of work.
- Included minutes never apply to larger runners, storage, public repositories or self-hosted runners.
- The detailed usage report is the only view that names the workflow file behind a line.
Frequently asked questions
What counts as a GitHub Actions minute?
Are GitHub Actions minutes counted per job or per workflow run?
Why does my usage report show more minutes than my jobs ran?
Can I buy more GitHub Actions minutes?
Related guides
References
- GitHub: Actions runner pricing, per-minute rates, billing SKUs and the rounding rule (verified 2026-09-20)
- GitHub Actions billing: included minutes, storage and what is free (verified 2026-09-20)
- GitHub: usage report types, columns and retention (verified 2026-09-20)
- GitHub Actions limits: execution time, queue time and concurrency (verified 2026-09-20)
- Latchkey pricing: published per-minute runner rates and plan fees (verified 2026-09-20)
- GitHub Actions documentation