← FinOpsAid blog

Where are our CI minutes going? A guide to reading the GitHub Actions page
Modeled spend, total runs, success rate, average duration, runner health and cache storage — every card on the FinOpsAid Actions page, and which numbers reconcile to a bill.
Actions is the page where a usage signal and a dollar figure sit closest together, and where the gap between them matters most. GitHub bills Actions by the minute against an included allowance; what it reports to you is minutes, and what this page shows you as dollars is those minutes with a rate applied. The tile says "Modeled Spend" precisely so nobody forgets.
The conventions used below come from the grammar behind every number.
The KPI row
| Tile |
What it counts |
Direction |
| Modeled Spend |
Actions cost derived by applying a rate to billable minutes. Not a billed figure. |
Worse. |
| Total Runs |
Workflow runs in scope. |
Neutral — runs aren't the cost driver; minutes are. |
| Success Rate |
Share of runs that succeeded, to one decimal place. |
Higher is better. One of the "up is good" tiles. |
| Avg Duration |
Mean run duration in minutes. |
Lower is better — usually. See the caveat. |
| Runners |
Total registered runners, with the online count as a footnote. |
Neutral. Detail on Runners. |
Avg Duration deserves a caveat. It's a mean across every workflow, so a nightly job that runs for two hours drags it up and tells you nothing about the pull-request feedback loop that developers actually feel. If the number looks bad, go to the per-workflow table before you conclude anything — the mean is a starting point, not a diagnosis.
Success Rate is a cost metric here, not just a quality one. A failed run bills the minutes it consumed before it failed. At a 90% success rate, roughly a tenth of your CI minutes bought nothing. That is the most direct link between reliability and spend anywhere in the product.
This is the arithmetic that makes reliability work fundable. The exact split is approximate — failed runs are usually shorter than successful ones — but the direction is right and the argument survives scrutiny.
Actions minutes over time
A daily bar chart of billable runner minutes, scoped by the Period filter. Minutes, not dollars — this is the honest series, and it's the one to screenshot when someone asks what drove the bill.
Look for shape, not level. A weekday sawtooth with quiet weekends is a healthy pattern. A flat line that never dips is scheduled work running regardless of whether anyone is developing — the cron problem covered in Actions costs hiding in plain sight.
Top Workflows by Minutes
A table of the eight heaviest workflows: Workflow, Runs, Minutes — sorted by minutes descending, each name linking to a per-workflow detail page.
This is where the Avg Duration tile becomes actionable. High minutes with low runs means a small number of very long jobs; high runs with moderate minutes means something fires constantly. Those are different problems: the first is a caching or parallelism question, the second is a trigger-configuration question.
The workflow detail page shows Modeled Cost, Runs, Success (with the failed count beside it, and marked as a higher-is-better metric), Minutes, a daily minutes chart, and a recent-runs table listing run ID, repository, conclusion and duration. That runs table is where you confirm a suspicion — a workflow whose recent conclusions alternate between success and failure is flaky, not broken.
Runner health
Four counters and a cost list.
| Counter |
Meaning |
| Online |
Registered and reachable. |
| Busy |
Currently executing a job. |
| Idle |
Online but not executing. |
| Offline |
Registered but unreachable. |
Underneath, a ranked list of the six most expensive runners by modeled monthly cost, labelled with name and OS.
Read these as a set. Persistent Idle across many runners means you're paying for capacity that never gets used — the fleet is oversized. Persistent Busy across all of them means jobs are queueing, and the cost you can't see is developers waiting. Offline runners are the awkward case: they consume no compute, but if they're VMs someone forgot to deprovision, the infrastructure bill continues regardless of what GitHub thinks of them.
Self-hosted runner cost is modeled from infra rates you supply, so its accuracy is exactly as good as those rates. Full detail is on the Runners page.
Actions cache storage
The last card, and one that only appears when there's data. It shows billed cache storage — the org total in GB and the number of caches, then a per-repository table of cache count and size.
This card is billed, not modeled. Cache storage is a real line item, and it accumulates in a way that surprises people: caches are created eagerly by workflows and evicted lazily, so a repository that ran an aggressive caching strategy for one release can hold gigabytes for a long time afterwards. Archived repositories still hold cache.
The reason it lives on the Actions page rather than Storage is that its cause is here — a workflow configuration created it, and a workflow configuration change is what fixes it.
What people get wrong on this page
- Quoting Modeled Spend as the Actions bill. It's minutes × rate. The minutes are real; the rate is applied by us.
- Reading Avg Duration as the PR feedback time. It's a mean across all workflows including nightly jobs.
- Treating Success Rate as purely a quality metric. Failed minutes are billed minutes.
- Ignoring Idle runners. Idle is the cost of over-provisioning, and nothing else on GitHub reports it.
- Forgetting cache storage exists. It bills, it accumulates silently, and nothing prompts a cleanup.
The 60-second read
- Minutes-over-time chart shape first: does it dip at weekends?
- Success Rate against the modeled spend — multiply the failure share by the spend and you have your reliability business case.
- Top Workflows by Minutes, and check runs-versus-minutes to classify the problem.
- Runner health counters as a set — Idle-heavy or Busy-heavy tells you which way to size.
- Cache storage total, if the card is present. It's usually the number nobody has ever looked at.
Frequently asked questions
Is the GitHub Actions spend figure a billed amount?
No, it is modeled — billable minutes multiplied by a rate, which is why the tile reads Modeled Spend. The minutes themselves are real and reported by GitHub. Use minutes when you need a figure that reconciles, and the dollar value for ranking and rough sizing.
How much does a low CI success rate actually cost?
Multiply your failure share by your Actions spend. A 90% success rate on a $40,000 CI bill means roughly $4,000 went on runs that produced nothing, because failed runs bill the minutes they consumed. That arithmetic is what makes reliability work fundable.
Why is Actions cache storage on the Actions page rather than Storage?
Because its cause lives here. Cache storage is billed, accumulates silently as workflows create entries eagerly and evict them lazily, and is fixed by changing a workflow's caching strategy. Putting it beside the workflows that created it puts it in front of the person who can act.
Want to see your own CI economics? Connect your GitHub org — read-only and free during beta — or explore the demo first. Next: how to read the Runners page.