Skip to content
Latchkey

How to Measure What Your GitHub Actions Actually Cost

Most teams optimise the job they assume is expensive. Pull the numbers first: the answer is usually dependency install, a wide matrix, or re-runs, and almost never the step people were about to rewrite.

GitHub shows you a total, which tells you that CI costs money and nothing about where it goes. Before changing a single workflow, get a per-workflow and per-job breakdown, because optimisation aimed at the wrong step is the most common way teams spend a sprint and save nothing.

There are three numbers worth having: minutes by workflow, minutes by job within the expensive workflows, and the share of runs that are re-runs of a previous failure. The third is the one almost nobody measures and frequently the largest.

Minutes by workflow

Terminal
# per-workflow usage for the repository
gh api /repos/{owner}/{repo}/actions/workflows --paginate \
  --jq '.workflows[] | "\(.id)\t\(.name)"' |
while IFS=$'\t' read -r id name; do
  ms=$(gh api "/repos/{owner}/{repo}/actions/workflows/$id/timing" \
        --jq '[.billable[]?.total_ms] | add // 0')
  printf "%8.1f min  %s\n" "$(echo "$ms/60000" | bc -l)" "$name"
done | sort -rn

Where the minutes go inside a workflow

Terminal
# per-job duration across recent runs of one workflow
gh run list --workflow=ci.yml --limit 50 --json databaseId --jq '.[].databaseId' |
while read -r id; do
  gh api "/repos/{owner}/{repo}/actions/runs/$id/jobs" \
    --jq '.jobs[] | [.name, (((.completed_at|fromdate) - (.started_at|fromdate))/60)] | @tsv'
done | awk -F'\t' '{s[$1]+=$2; n[$1]++} END {for (k in s) printf "%8.1f min avg  %4d runs  %s\n", s[k]/n[k], n[k], k}' | sort -rn

The number nobody measures: re-run share

A re-run buys the same work twice. If a meaningful share of your runs are retries of a previously failed run, that is pure waste and no per-minute discount touches it.

Terminal
# what fraction of recent runs are attempt 2 or later?
gh run list --limit 200 --json databaseId,conclusion --jq '.[].databaseId' |
while read -r id; do
  gh api "/repos/{owner}/{repo}/actions/runs/$id" --jq '.run_attempt'
done | awk '{t++; if ($1>1) r++} END {printf "re-runs: %d of %d (%.1f%%)\n", r, t, 100*r/t}'

Convert minutes to money correctly

RunnerRate10,000 min/month
Linux 2-core$0.006/min$60
Linux 4-core$0.012/min$120
Linux 8-core$0.022/min$220
Windows 2-core$0.010/min$100
macOS 3-4 core$0.062/min$620

Now decide what to change

  • Install dominates: cache the dependency directory and key it to the lockfile hash.
  • A wide matrix of short jobs dominates: the per-minute rounding is the cost. Consolidate jobs or move to a per-second biller.
  • One long job dominates: shard it, or move that job alone to a larger or faster runner.
  • Re-runs dominate: nothing about runner choice fixes this. Find the flaky failures and address them at source.
  • macOS dominates: it is 10x Linux per minute. Move anything that does not genuinely need macOS.

Frequently asked questions

How do I see GitHub Actions minutes by workflow?
Use the workflow timing API: gh api /repos/{owner}/{repo}/actions/workflows/{id}/timing returns billable milliseconds per workflow. Loop it over the workflow list to get a ranked breakdown, which the billing UI does not provide.
Are GitHub Actions minutes rounded?
Yes, each job is rounded up to the nearest minute. A 40-second job bills as a full minute, so a matrix of many short jobs costs substantially more than its actual runtime. This is why per-second billing is a real differentiator on wide matrices.
Do public repositories cost anything?
No. Standard GitHub-hosted runners are free and unlimited on public repositories, and public repos get a larger 4 vCPU and 16 GB machine. Larger runners are billed even on public repositories.
What is the biggest hidden CI cost?
Re-runs. A retry of a failed job buys the same work twice, and the failure is often unrelated to the code. Measure your re-run share before optimising your per-minute rate; above a few percent it dominates any rate difference available.

Related guides

References

Run this faster and cheaper on Latchkey managed runners - self-healing included. Start free → 30-day trial · No credit card