Reference
How GitHub Actions billing works
By Keith Mazanec, Founder, CostOps · Updated February 17, 2026
GitHub Actions billing combines three systems: included minutes from your GitHub plan, OS-based multipliers (Linux 1x, Windows 2x, macOS 10x), and per-minute charges for larger runners. Standard runners draw from an included pool of 2,000 to 50,000 monthly minutes depending on your plan. Larger runners (4+ cores) bypass the pool entirely and always bill per-minute at rates starting at $0.016/min.
Understanding how these three layers interact is the first step to controlling CI cost. This guide covers each billing layer, how minutes are metered and rounded, what usage is free, and where costs hide.
Layer 1
Included minutes by plan
Every GitHub plan includes a monthly pool of Actions minutes: 2,000 for Free, 3,000 for Pro and Team, and 50,000 for Enterprise Cloud. These minutes reset on your billing date and do not roll over. Public repositories consume zero included minutes because standard runner usage on public repos is free on all plans. Private and internal repositories draw from the pool.
| GitHub plan | Included minutes | Overage rate (Linux) |
|---|---|---|
| Free | 2,000 | $0.006/min |
| Pro | 3,000 | $0.006/min |
| Team | 3,000 | $0.006/min |
| Enterprise Cloud | 50,000 | $0.006/min |
The included pool is measured in Linux-equivalent minutes. This matters because Windows and macOS runners consume minutes at higher rates (covered in Layer 2). A team on the Free plan with 2,000 minutes could exhaust the pool with just 200 minutes of macOS usage.
Once included minutes are exhausted, GitHub charges per-minute at the overage rate until the billing cycle resets. If you have a spending limit set to $0 (the default for Free and Pro), workflows simply stop running once included minutes are gone. Team and Enterprise plans can set a higher spending limit to allow overages.
Layer 2
OS minute multipliers: Linux 1x, Windows 2x, macOS 10x
GitHub Actions applies OS-based multipliers to minute consumption: Linux uses 1x, Windows uses 2x, and macOS uses 10x. One wall-clock minute on a macOS runner costs 10 included minutes from your pool. This multiplier also applies to overage charges, so if you're past your included minutes, macOS costs 10× the Linux overage rate per minute.
1×
Linux
1 min used = 1 min billed
2×
Windows
1 min used = 2 min billed
10×
macOS
1 min used = 10 min billed
This is the most common source of surprise in Actions billing. A workflow that runs 100 minutes of macOS builds per month consumes 1,000 included minutes, which is half the Free plan's entire allocation. The same workflow on Linux would consume only 100.
| Runner OS | Wall-clock | Multiplier | Minutes billed |
|---|---|---|---|
| Linux | 100 min | 1× | 100 |
| Windows | 100 min | 2× | 200 |
| macOS | 100 min | 10× | 1,000 |
Rounding matters: GitHub rounds each job's minutes up to the nearest whole minute. A job that runs for 15 seconds is billed as 1 minute. On macOS, that 15-second job costs 10 included minutes. This means many short jobs cost more per minute of actual compute than fewer longer jobs.
Layer 3
Larger runners bill separately from included minutes
No. GitHub-hosted larger runners (4-core and above) operate on an entirely different billing model. They do not draw from your included minutes pool. Instead, they are always billed per-minute at a fixed rate, regardless of whether you have included minutes remaining.
Team / Enterprise Cloud Larger runners require a GitHub Team or Enterprise Cloud plan. They are not available on Free or Pro plans.
Standard runners (2-core)
Larger runners (4+ core)
This means a team could have thousands of unused included minutes while still receiving a large bill for larger runner usage. The two billing streams appear on the same invoice but are completely independent. See our pricing reference for the full rate card.
Exceptions
What GitHub Actions usage is free?
Three categories of GitHub Actions usage are always free, regardless of plan: public repository standard runners, self-hosted runners, and queue/setup time before job execution begins.
-
Public repositories. All standard runner usage on public repos is free. No included minutes are consumed. This includes Linux, Windows, and macOS standard runners. Larger runners on public repos are still billed per-minute.
-
Queue and setup time. Billing starts when the job begins executing, not when it's queued. The time a job spends waiting for a runner is free. However, setup actions like actions/checkout are part of job execution and are billed.
-
Self-hosted runners. Jobs that run on your own infrastructure are never billed by GitHub. You pay for the compute through your cloud provider or hardware, but GitHub charges nothing for orchestration.
Update — December 2025
GitHub proposed charging for self-hosted runner orchestration, then paused. On December 17, 2025, GitHub announced pricing changes that included a new $0.002/min "Actions cloud platform" charge for self-hosted runners on private repositories, effective March 1, 2026. The rationale was that self-hosted runner customers were leveraging GitHub's orchestration infrastructure (job queuing, routing, logging, secrets management) at no cost, with those costs being subsidized by GitHub-hosted runner pricing.
The community pushed back sharply. Many teams chose self-hosted runners specifically to avoid per-minute GitHub charges, and viewed an orchestration fee as a tax on their own infrastructure. Within the same day, GitHub postponed the change, stating: "We missed the mark with this change by not including more of you in our planning." The self-hosted runner charge is on hold indefinitely while GitHub re-evaluates.
As of February 2026, self-hosted runners remain free on all plans. However, this may change. If you rely heavily on self-hosted runners, it's worth tracking the GitHub community discussion for updates. GitHub Enterprise Server customers are exempt from any proposed changes.
Metering
How does GitHub count Actions minutes?
GitHub meters Actions usage at the job level, not the workflow level. Each job in a workflow is timed independently, rounded up to the nearest whole minute, then multiplied by the OS multiplier. A 15-second job is billed as 1 full minute. This per-job rounding has practical implications for how you structure workflows.
Workflow run: Job 1 (lint): 45 seconds → rounded to 1 min Job 2 (build): 3 min 10 sec → rounded to 4 min Job 3 (test): 7 min 02 sec → rounded to 8 min Total billed: 13 min (not 11 min actual) Rounding overhead: 2 min (18%)
The rounding penalty is proportionally worse for short jobs. A workflow with 10 jobs that each take 30 seconds consumes 10 billed minutes for 5 minutes of actual compute, resulting in 100% overhead. Consolidating those into fewer jobs reduces wasted minutes. See our guide on too many small jobs for strategies.
Parallel jobs bill independently. If your workflow runs 4 jobs in parallel, each taking 5 minutes, you're billed for 20 minutes total, not 5 minutes. Parallelism saves wall-clock time for developers but doesn't save billable minutes. It can increase them due to per-job rounding.
Controls
How do GitHub Actions spending limits work?
GitHub Actions spending limits cap overage charges after included minutes are exhausted. The default spending limit is $0, which stops workflows entirely once the pool runs out. This setting only affects charges beyond included minutes and does not limit usage of included minutes themselves.
| Limit setting | Behavior |
|---|---|
| $0 (default) | Workflows stop when included minutes are exhausted. No overage charges. |
| $N (custom) | Allows up to $N in overage charges per billing cycle. Workflows stop after the limit. |
| Unlimited | No cap. You're billed for all usage beyond included minutes with no cutoff. |
Spending limits don't apply to larger runners. Larger runner charges are billed separately and are not affected by the Actions spending limit. If you use larger runners, set up billing alerts in your GitHub organization settings, or use a tool like CostOps that tracks both standard and larger runner spend in one place, to avoid surprises.
Where costs hide
Why is my GitHub Actions bill so high?
Most GitHub Actions cost problems fall into six categories: running CI too often, doing too much work per run, recomputing cached work, flaky test reruns, artifact storage bloat, and runner size mismatch. Each one interacts with the billing rules above in a different way.
-
CI runs too often. Duplicate triggers, docs-only changes running full CI, and cron jobs on inactive repos all burn billed minutes with zero value.
-
Too much work per run. Matrix builds with 20 combinations turn 13 minutes of compute into 20 billed minutes due to per-job rounding. Expensive E2E tests run on every push instead of just before merge.
-
Recomputing the same work. A broken cache key means a full dependency install on every job. A missing .dockerignore sends gigabytes to the Docker daemon. These are billed minutes spent redoing work that's already been done.
-
Reruns & flakiness. A flaky test that fails and passes on rerun costs double. Clicking "re-run all jobs" re-executes every job, including the ones that already passed.
-
Artifacts & storage. Storage is billed separately from minutes. Uploading large artifacts on every run accumulates charges at $0.25/GB per month beyond your plan's included storage.
-
Runner mismatch. A 20-minute build on a 2-core runner pays less per minute but more in total than the same build finishing in 8 minutes on a 4-core. Self-hosted runners running 24/7 don't appear on your GitHub bill but show up on your cloud bill.
Visibility
How to check your GitHub Actions usage and spending
GitHub provides usage data in four places: billing settings, CSV usage reports, the Actions tab per run, and the REST API. Each offers a different level of detail, and none provides a complete cost breakdown on its own.
| Where | What you see | Limitation |
|---|---|---|
| Billing settings | Total minutes used, spending this cycle | No per-workflow breakdown |
| Usage report (CSV) | Per-repo and per-workflow minutes | Monthly export, no job-level detail |
| Actions tab (per run) | Individual job durations | No cost calculation, manual inspection |
| REST API | Workflow run and job timing data | Requires building your own aggregation |
The gap between "what is this costing?" and "why is it costing that?" is where most teams struggle. GitHub's billing page shows totals, but doesn't tell you which workflow, repository, or runner type is driving the number. To answer those questions, you need per-job timing data from the API, combined with the rate card for each runner type. CostOps does this automatically by pulling job-level timing from the GitHub API and applying the correct per-minute rate to give you cost breakdowns by workflow, repository, and runner type.
Quick reference
GitHub Actions billing rules at a glance
Metering unit: per job, rounded up to nearest minute Multipliers: Linux 1×, Windows 2×, macOS 10× Public repos: free (standard runners only) Self-hosted runners: free (you pay your infra provider) Larger runners: always per-minute, never uses included pool Queue time: free (billing starts at job execution) Canceled jobs: billed for time already executed Reruns: billed as new job executions Included pool reset: monthly on billing date, no rollover Spending limit: caps overages, does not apply to larger runners
Related guides
GitHub Actions Pricing
Complete per-minute rate card for every runner type, OS, and size.
Underpowered Runners
When a bigger runner costs less total because it finishes faster.
Too Many Small Jobs
Per-job rounding means many short jobs waste more minutes than fewer long ones.
Canceled Runs Wasting Minutes
Canceled workflows still cost for time already consumed.