Skip to main content
RunBook Academy

Git, CI/CD & GitOpsC · Runner CapacityCost

Cost of hosted versus self-hosted runners — the financial trade-off

Advanced⏱ ~22 mingit

What you'll learn

  • Decompose the cost of hosted runners into per-minute rates and included minutes
  • Decompose the cost of self-hosted runners into compute, operations, and risk premiums
  • Compute a break-even point between hosted and self-hosted for a given workload
  • Recognise when the cost comparison is dominated by factors beyond compute

Prerequisites

Verified against Git 2.55.x teaching target; 2.40+ minimum · GitHub Actions continuous service; Aug 2026 documentation baseline · Argo CD v3.5.x teaching target; v3.0+ minimum · Flux v2.9.x · Sigstore Cosign v3.1.x · SLSA v1.2 · OCI Distribution Specification v1.1 · Git LFS v3.7.1 · Kubernetes (cross-course target) 1.36.x

Not yet marked complete on this device.

The choice between hosted and self-hosted runners is often presented as a simple price comparison. It is not. Each option has cost components the other does not, and the break-even depends on the team’s operational capacity as much as it does on the per-minute rate.

Cost components of hosted runners

GitHub-hosted runners are priced by per-minute rate, with monthly included minutes per plan:

flowchart LR
  H["Hosted runner cost"] --> R["Per-minute rate\n(by runner class)"]
  H --> S["Storage overage\n(GB-month)"]
  H --> O["Operational overhead\nzero"]
  H --> T["Time overhead\ncold-start, image pull,\nephemeral cleanup"]
  • Per-minute rate. Published in GitHub’s billing documentation. Different for Linux, Windows, macOS, and for larger-runner classes. The visible number.
  • Storage overage. Beyond the included GB-month, storage costs extra. Often invisible until the bill arrives.
  • Operational overhead. Zero. GitHub patches the host, rotates the image, and reclaims the VM. This is the single largest line item, even though it appears as zero on the invoice.
  • Time overhead. Cold-start latency on the hosted runner is small but non-zero, and the runner is ephemeral
    • state does not survive across jobs unless cached.

Cost components of self-hosted runners

Self-hosted runners invert every line item:

flowchart LR
  S["Self-hosted cost"] --> C["Compute\nVM or pod"]
  S --> OPS["Operations\npatching, image,\nregistration, secrets"]
  S --> RISK["Risk premium\ncompromise, persistence,\ncompliance"]
  S --> TIME["Time overhead\nvariable cold-start"]
  • Compute. The VM, the bare-metal host, or the Kubernetes pod. Billed by the cloud provider or amortised across on-premises hardware.
  • Operations. Patching the host, rebuilding the runner image, registering and deregistering runners, rotating the registration token, managing secrets on the runner. This is real engineering time, often the largest hidden cost.
  • Risk premium. A self-hosted runner is an actor in the CI/CD threat model. A compromise is a production compromise; persistence between jobs is a feature of the platform. Compliance overhead and incident response cost should be priced in.
  • Time overhead. Variable: a warm self-hosted runner has near-zero cold start; a scale-to-zero ARC pool has a Kubernetes pod-startup cost that hosted runners do not have.

Computing break-even

The break-even is the workload size at which the operational overhead of self-hosted is paid back by the compute savings. A simplified model:

HOSTED_RATE=0.008
SELF_RATE=0.002
OPS_OVERHEAD_USD_MONTH=2000
JOB_MIN_PER_MONTH=100000

HOSTED_COST=$(awk -v r="$HOSTED_RATE" -v m="$JOB_MIN_PER_MONTH" \
  'BEGIN { printf "%.0f", r*m }')
SELF_COST=$(awk -v r="$SELF_RATE" -v m="$JOB_MIN_PER_MONTH" \
  'BEGIN { printf "%.0f", r*m }')
echo "Hosted: $HOSTED_COST; Self-hosted compute: $SELF_COST"
echo "Self-hosted total: $((SELF_COST + OPS_OVERHEAD_USD_MONTH))"

For 100,000 job-minutes/month at these rates, hosted costs $800 and self-hosted compute costs $200 - but the operational overhead is $2,000/month, so self-hosted loses on a small workload and wins on a large one.

When the comparison is dominated by other factors

The cost comparison is dominated by compute in only one case: a large, stable workload with no special requirements. Most teams have at least one of these complicating factors:

  • Specialised hardware. GPUs, large-memory, ARM, macOS. Hosted runners offer these as larger runners at a premium; self-hosted requires buying or renting the hardware. The comparison shifts towards hosted.
  • Network proximity. A runner that needs to talk to a private VPC over a VPN is much faster on self-hosted. The speedup compounds across the day’s jobs.
  • Compliance. A runner that must not have access to public network, or that must run on FIPS-validated hosts, may be impossible on the hosted platform.
  • Burst. A workload that spikes to 100 concurrent jobs once a quarter is cheaper on hosted - the burst does not have to be provisioned for year-round.

Production discipline

  1. Price the operations, not just the compute. Compute is visible; operations are not.
  2. Re-derive the break-even annually. Cloud prices move; operational cost changes as the team grows.
  3. Hybrid is the realistic answer. Production-sensitive workloads on self-hosted with strict IAM; sporadic or experimental workloads on hosted.
  4. Don’t optimise for the bill; optimise for the total cost. Risk premiums and incident response are part of the total.
  5. Document the decision. The hosted-vs-self decision changes; the reasoning should be in the capacity plan.

Cross-course references

  • Git, CI/CD & GitOps - Parts XL (Runners) and LXVI (Supply) cover the security framing of the decision.
  • FinOps for Production Sysadmins - Part IV (BuildVsBuy) covers the same trade-off for general workloads.
  • Kubernetes for Production Sysadmins - Part XXIX (Cost) covers cluster cost components in depth.

Quiz

Knowledge check · 4 questions

  1. Q1. Which cost component is most often missing from a naive hosted-vs-self-hosted comparison?

  2. Q2. Self-hosted runners are not always cheaper than hosted runners once a team runs more than 1,000 jobs per month.

  3. Q3. Name the three non-compute cost components of self-hosted runners that a hosted-runner comparison must include.

  4. Q4. Recommend a hosted-vs-self-hosted split for a team running production CI on a private VPC with periodic burst to 80 concurrent jobs.

    Team T runs 80,000 job-minutes/month on average. They have a private VPC that all jobs must reach. Once a quarter they have a release-week burst of 200,000 job-minutes in 48 hours. They have a small platform team with no Kubernetes experience but strong AWS expertise.

Passing score: 75%. Answers are checked in this browser.