GitHub Actions pricing looks simple until a private workflow uses a different operating system, stores artifacts for weeks, or runs again after a failed test. The useful way to think about the bill is as three separate counters: included minutes, runner rates, and storage. This guide checks GitHub’s published pricing and usage rules as of August 2, 2026, then turns them into practical decisions you can use in a real repository.
The short version: standard GitHub-hosted runners are free in public repositories, private repositories receive a monthly allowance based on the account plan, and usage above that allowance is billed by runner type. GitHub also says self-hosted runner usage is free, but you still pay for the machine and the work of operating it. GitHub’s Actions billing documentation is the source of truth when your account’s billing settings do not match a simple example.
What GitHub Actions charges for
There are two things people usually call “Actions usage,” but they behave differently.
- Runner time: the processing time used by jobs on GitHub-hosted runners. The repository owner pays, not the person who clicked Run workflow.
- Storage: artifacts, GitHub Packages, caches, and custom runner images. Storage is measured over time, so deleting a large artifact today does not erase the hours it already occupied this billing cycle.
Standard runners in public repositories do not consume a paid minute allowance. The same is true for GitHub Pages and Dependabot. Larger GitHub-hosted runners are always charged, including when a repository is public or the plan still has unused included minutes. GitHub documents these exceptions in its billing reference.
How many Actions minutes each plan includes
For private repositories, GitHub resets the included minute allowance at the start of each billing cycle. The allowance is attached to the account or organization that owns the repository. GitHub’s current usage table is the one to check before changing plans, because the plan price and included products can change independently.
- GitHub Free: 2,000 minutes per month, 500 MB of shared artifact and Packages storage, and 10 GB of cache storage per repository.
- GitHub Pro: 3,000 minutes per month, 1 GB of shared artifact and Packages storage, and 10 GB of cache storage per repository.
- GitHub Free for organizations: 2,000 minutes per month, 500 MB of shared artifact and Packages storage, and 10 GB of cache storage per repository.
- GitHub Team: 3,000 minutes per month, 2 GB of shared artifact and Packages storage, 10 GB of cache storage per repository, and 75 GB of custom image storage.
- GitHub Enterprise Cloud: 50,000 minutes per month, 50 GB of shared artifact and Packages storage, 10 GB of cache storage per repository, and 150 GB of custom image storage.
The “shared” part matters. Actions artifacts and GitHub Packages draw from the same plan allowance. Cache storage is separate, and the included cache allowance is per repository rather than one pool for the entire organization. The complete table is in GitHub’s product usage reference.
Runner prices: Linux is the default for a reason
Once included minutes are used, GitHub bills based on the runner SKU. The current baseline rates for private repository usage are:
- Linux 1-core x64, using ubuntu-slim: $0.002 per minute.
- Linux 2-core x64, using ubuntu-latest or another standard Ubuntu label: $0.006 per minute.
- Linux 2-core arm64: $0.005 per minute.
- Windows 2-core x64: $0.010 per minute.
- Windows 2-core arm64: $0.010 per minute.
- macOS 3-core or 4-core: $0.062 per minute.
That makes macOS roughly ten times the price of a standard Linux minute at the listed rates. Use macOS when you need Apple tooling, not as a general-purpose runner for tests that also run on Linux. The GitHub-hosted runner reference lists the labels and machine specifications, while the Actions billing page lists the billing SKUs and rates.
A useful mental model is that a workflow with 1,000 billable Linux minutes costs about $6 at the standard Linux rate. The same 1,000 minutes on Windows costs $10, and on macOS costs $62. Your actual bill also depends on how much of the run fits inside the plan allowance.
A simple way to estimate your monthly bill
Start with the usage report for the account or organization that owns the repository. Separate the total by runner type, subtract the included allowance, and multiply each remaining bucket by its runner rate. Then add storage overages.
runner overage cost =\n (Linux minutes × 0.006)\n+ (Windows minutes × 0.010)\n+ (macOS minutes × 0.062)\n+ (other runner rates from GitHub’s pricing reference)\n\nstorage overage =\n shared storage GB-months × 0.25\n+ cache GB-months × 0.07\n+ custom image GB-months × 0.07For example, 1,000 Linux minutes beyond the included allowance is about $6. GitHub’s own example uses 5,000 overage minutes split between 3,000 Linux minutes and 2,000 Windows minutes, for $38 total. Treat examples as estimates, since the billing dashboard may show spend instead of raw minutes and larger runners have their own rates.
Why failed runs and re-runs still cost money
Actions measures the time a job actually ran. A job that fails after five minutes uses five minutes. If you fix the problem and re-run the job successfully for ten minutes, the two runs use fifteen minutes together. This is why a noisy workflow can spend more than its green runs suggest.
The same rule applies to pull request workflows that are triggered repeatedly. A force-push, a manual re-run, and a workflow triggered by both push and pull_request can all create another run. Before optimizing runner size, remove accidental duplicate triggers.
Storage is the other half of the bill
Artifacts are useful for test reports, coverage, packaged builds, and debugging. They are also easy to leave behind. GitHub measures artifact and cache storage over time, in GB-hours, rather than looking only at what exists at the end of the month. Deleting an artifact stops future accumulation but does not remove storage already accrued during the billing cycle.
- Keep short-lived pull request artifacts for a few days, not forever.
- Upload only the files a person can use to debug or release the run.
- Use a separate artifact policy for release builds that must be retained longer.
- Delete stale Packages versions and review cache growth per repository.
- Remember that artifacts and GitHub Packages share the plan’s shared storage allowance.
GitHub’s current overage rates are $0.25 per GB-month for shared artifact and Packages storage, $0.07 per GB-month for Actions cache, and $0.07 per GB-month for custom runner images. The billing page explains why the dashboard’s current storage number and the month’s accrued bill can differ.
The best cost controls to add first
You do not need a complicated cost platform to stop most waste. Start with the controls that remove work nobody needed.
- Cancel stale pull request runs. Add a concurrency group with cancel-in-progress for checks where only the newest commit matters. See GitHub Actions concurrency for the pattern.
- Avoid duplicate events. Decide whether a check needs push, pull_request, merge_group, schedule, or workflow_dispatch. Adding every event by habit can double or triple usage.
- Use path filters. Documentation-only changes do not always need the full application matrix. Keep a small documentation job if docs still need validation.
- Keep the matrix honest. Every matrix combination is another job. Run the broad operating system and version matrix on the branches that need it, and use a smaller fast path for normal pull requests when your risk model allows it.
- Prefer Linux for portable work. Reserve Windows and macOS for code that actually depends on their toolchains.
- Cache dependencies, not everything. A cache that is too broad becomes stale, expensive to restore, and hard to invalidate. Key it from the lockfile and the runner or runtime version when those inputs matter.
- Set artifact retention intentionally. A three-day pull request report and a ninety-day release bundle should not use the same retention policy.
- Measure wall-clock time separately from billed time. Parallel work can shorten feedback while still using similar compute, so do not call a workflow cheaper just because it finishes sooner. See parallel Actions steps for the execution trade-offs.
These controls also make CI easier to reason about. A workflow should say why it runs, what it produces, and how long the result needs to exist.
A small workflow template with safer defaults
This illustrative workflow cancels obsolete pull request runs, grants only read access to repository contents, and keeps a build artifact for three days. Adjust the commands and action versions to match your repository.
name: CI\n\non:\n push:\n branches: [main]\n pull_request:\n\npermissions:\n contents: read\n\nconcurrency:\n group: ci-${{ github.workflow }}-${{ github.ref }}\n cancel-in-progress: true\n\njobs:\n test:\n runs-on: ubuntu-latest\n steps:\n - uses: actions/checkout@v4\n - run: npm ci\n - run: npm test\n - uses: actions/upload-artifact@v4\n if: always()\n with:\n name: test-report\n path: reports/\n retention-days: 3Self-hosted runners: free minutes do not mean free CI
GitHub’s current billing documentation says self-hosted runner usage is free. That is different from free infrastructure. You still pay for the machine, storage, networking, patching, runner upgrades, monitoring, and the security work required to isolate untrusted pull request code.
GitHub announced a planned $0.002-per-minute cloud platform charge for self-hosted runner usage, then postponed that change in December 2025 while it re-evaluated the approach. Do not copy an old migration plan into a new budget without checking the current billing documentation and the pricing change announcement.
Budget and alert settings worth enabling
If an account has no valid payment method, GitHub can block usage after the included quota is exhausted. If a payment method is present, a budget can stop or limit metered usage. GitHub also supports included-usage alerts at 90% and 100% for Actions minutes and storage.
- Set a small test budget before enabling larger runners.
- Opt in to 90% and 100% included-usage alerts.
- Review usage by repository and runner type before increasing a plan.
- Keep a written owner for billing settings so a workflow change does not surprise the whole team.
The GitHub budgets and alerts guide explains the controls, and the billing and usage guide explains how to view Actions usage and repository-level metrics.
A practical monthly review
- Check the top repositories by minutes and compare them with their trigger volume.
- Check macOS and Windows usage separately. They are often the first place an unnecessary matrix becomes expensive.
- Look for re-runs and cancelled jobs that ran for a long time before being replaced.
- Review artifact retention and the largest Packages versions.
- Compare current usage with the included allowance before changing plans.
- Keep one recent usage report so you can spot a trend instead of reacting to a single busy week.
GitHub Actions is usually affordable when the workflow is selective. The expensive habits are predictable: duplicate triggers, oversized matrices, long-lived artifacts, and premium runners used for portable work. Start with those four. Then use budgets and usage reports to confirm that the changes actually moved the bill.
For the current allowances and rates, bookmark GitHub’s Actions billing reference and the product usage table. Pricing changes over time, but the operating principles stay useful: know who owns the bill, know which runner did the work, and make every retained artifact earn its place.
