Why GitHub Actions minutes run out, with the math
On a private repository, GitHub Free includes 2,000 Actions minutes a month. Most people who run out did not run something huge; they met one of four multipliers they did not know were there. Here is each one with the arithmetic, so you can check your own workflows.
1. Every job rounds up to a whole minute
GitHub's runner pricing page says it "rounds the minutes and partial minutes each job uses up to the nearest whole minute" (source). A health check that takes 20 seconds bills 1 minute. Run on a schedule, that adds up quickly (a month averaged over a year, one billed minute per run):
| Schedule | Cron | Runs a month | Share of 2,000 free minutes (standard Linux runner) |
|---|---|---|---|
| every 5 minutes | */5 * * * * | 8,760 | 438% |
| every 10 minutes | */10 * * * * | 4,380 | 219% |
| every 15 minutes | */15 * * * * | 2,920 | 146% |
| every 30 minutes | */30 * * * * | 1,460 | 73% |
| every hour | 0 * * * * | 730 | 37% |
| once a day | 0 6 * * * | 30 | 2% |
One developer described exactly this on dev.to in September 2026: the free-tier billing block "hit in May" and "hit again in late June" on a pipeline of daily jobs that were "individually cheap — 2–4 minutes per run — but daily crons multiply fast" (post).
2. A matrix multiplies, and each leg has its own price
A matrix of 3 operating systems and 3 Node versions is 9 jobs, not 1. At 5 minutes each that is 45 billed minutes for one run: 3 Linux jobs (3 x 5 min x $0.006), 3 Windows jobs (3 x 5 min x $0.010) and 3 macOS jobs (3 x 5 min x $0.062), which comes to $1.17 a run. The macOS third of the matrix is 79% of that cost.
3. The price per minute depends on the operating system
From GitHub's table (read 2026-10-12): Linux 2-core $0.006, Linux 1-core ubuntu-slim $0.002, Linux arm $0.005, Windows $0.010, macOS $0.062 per minute. macOS is about 10 times Linux. Larger runners are billed at their own rates even in public repositories.
4. No timeout means up to 360 minutes when something hangs
The default for timeout-minutes is 360 (workflow syntax). One hung job that is never cancelled bills: Linux $2.16, Windows $3.60, macOS $22.32. Setting a limit of about twice the normal run time caps that.
Two more that are easy to miss
- Push and pull_request together.
on: [push, pull_request]without a branch filter runs the workflow twice for a commit on a branch with an open pull request. Limitpushto your default branch. - Superseded runs. Without
concurrencyandcancel-in-progress, an older run keeps going after you push again.
Public repositories, and the shared allowance
Standard GitHub-hosted runners are free in public repositories, and for GitHub Pages and Dependabot. For private repositories the included minutes (Free 2,000, Pro and Team 3,000, Enterprise Cloud 50,000) are shared by everything on the account, so several small repositories can add up to one large bill. Without a payment method on file, usage is blocked once the quota is used (billing docs).
Work it out for your own files
Paste your workflows into the free minutes calculator to get the numbers above for your jobs, with the line that causes each charge. The same engine is a free command line tool (a VS Code extension is coming soon); see Minutemeter.