Skip to content
Latchkey LogoLatchkey home

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.

Per-job rounding adds 140%, 97%, 33% and 5% to 20 jobs of 25s, 61s, 3m01s and 9m30s
What per-job rounding adds to a 20-job matrix at four job lengths, computed from GitHub's rule that each job is rounded up to the whole minute, read on 20 September 2026.

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 takesMinutes usedMinutes billedBilled at $0.006
25 seconds8.320$0.12
61 seconds20.340$0.24
3 minutes 1 second60.380$0.48
9 minutes 30 seconds190.0200$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-onBilling SKU on the reportPer-minute rate
ubuntu-slimactions_linux_slim$0.002
ubuntu-latestactions_linux$0.006
ubuntu-24.04-armactions_linux_arm$0.005
windows-latestactions_windows$0.010
windows-11-armactions_windows_arm$0.010
macos-latestactions_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 columnWhat it holds on an Actions line
skuThe runner SKU that ran the job, for example actions_linux or linux_16_core
quantity and unit_typeBilled minutes, already rounded up job by job
applied_cost_per_quantityThe per-minute rate that line was charged at
discount_amountFree usage priced then discounted, which is how public-repo and self-hosted minutes appear
workflow_pathThe workflow file that produced the usage, in the detailed report only
net_amountWhat 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?
A minute of execution time on a GitHub-hosted runner, measured per job and rounded up to the next whole minute. Queue time is a separate thing in GitHub's own limits documentation, which allows a self-hosted job to sit in the queue for 24 hours and a hosted job to run for six hours. The account that owns the repository is charged, not the account that pushed.
Are GitHub Actions minutes counted per job or per workflow run?
Per job. Each job in a run is rounded up to a whole minute on its own, so a run with twelve jobs is twelve roundings. This is why adding matrix legs can raise the bill while lowering the wall clock, and why collapsing very short legs into fewer, longer ones is usually the cheapest change available on a Linux pipeline.
Why does my usage report show more minutes than my jobs ran?
Because the report shows billed minutes, which are already rounded up job by job. A matrix of twenty 25 second jobs uses 8.3 minutes of machine time and reports 20. The gap is not an error and there is no setting for it; the only lever is job length, since the waste is a fraction of a minute per job however short the job is.
Can I buy more GitHub Actions minutes?
Not as a pack. Once the included minutes for the cycle are gone, further standard-runner usage on private repositories simply bills at the per-minute rate for whichever runner ran it, provided the account has a valid payment method. Without one, GitHub blocks usage rather than billing it, which is the behavior running out of minutes covers.

Related guides

References

Fix the rounding first. The minutes that survive it are $0.0025 on Latchkey against $0.006 GitHub-hosted. Start free → 30-day trial · No credit card