DEV Community

Cover image for GitHub Actions minutes and billing, explained
Kay
Kay

Posted on Originally published at latchkey.dev

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 usage in your plan does and does 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 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

Computed from the rounding rule in Actions runner pricing, read 20 September 2026. Minutes used is 20 times the job length; minutes billed is 20 times that length rounded up to a whole minute.

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

SKUs and rates read from Actions runner pricing and labels from GitHub-hosted runners, both on 20 September 2026.

What the included usage covers, and the four rules around it

Your plan comes with a monthly amount of included compute usage, and it resets at the start of each billing cycle. Since 28 October 2026 it is a dollar amount rather than a minute count: $12 on GitHub Free, $18 on Pro and Team, $300 on Enterprise Cloud. GitHub deducts each job at its runner's per-minute rate, so $18 is 3,000 standard Linux minutes at $0.006, but 1,800 Windows minutes at $0.010 or about 290 macOS minutes at $0.062. GitHub's changelog calls the new form "one shared, dollar-based pool" and says "It's the same value", which holds for standard Linux minutes and not for Windows or macOS ones.

Each of the four rules 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: they draw on the included amount only on GitHub Team and Enterprise Cloud, the plans that offer them, and "Larger runners are not free for public repositories".
  • 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 lists them as usage that "remains free independently and does not reduce the included compute usage".

Quoted from GitHub Actions billing, Actions runner pricing and the 28 October 2026 changelog entry, read 12 November 2026.

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

Column names and report limits read from GitHub usage reports on 20 September 2026.

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 $18 of included usage comes off first, the price of 3,000 of those minutes, so the invoice is $82.50 less $18, 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.

FAQ

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 usage for the cycle is spent, 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.

References

Top comments (0)