Skip to content
Latchkey
Published June 2026

The 2026 Runner Economics Report

What a CI minute really costs across Linux, Windows, macOS, and GPU, why the sticker rate hides most of the true cost, and where the break-even line sits between managed and self-hosted runners.

$0.08
published cost of a macOS CI minute on hosted runners
GitHub Actions - billing & pricing
69%
modeled lower per-minute cost on managed runners versus GitHub-hosted Linux
Latchkey analysis (modeled)
41%
of paid self-hosted fleet capacity that sits idle on a typical workday
Latchkey analysis (modeled)

Executive summary

CI compute has quietly become one of the least-understood line items in an engineering budget. Most teams know their monthly runner bill as a single number but cannot break it down by operating system, by job, or by the share of minutes that did no useful work at all. That opacity is expensive, because the levers that move the bill are specific and the aggregate number hides every one of them. This report rebuilds those numbers from the ground up using published per-minute rates and modeled fleet utilization.

The headline is that the sticker price of a CI minute tells you almost nothing about its true cost. A self-hosted Linux minute looks cheap until you add the idle capacity you pay for between jobs, the engineering hours spent patching and scaling the fleet, and the queue time that quietly pushes developers to over-provision so they never wait. Once those are priced in, the per-minute comparison that made self-hosting look like a bargain inverts for most teams, and the inversion is not marginal.

On the hosted side, the operating system is the dominant cost variable, not the platform. A Linux minute is the cheap baseline, a Windows minute is about twice it, and a macOS minute is roughly ten times it, with a GPU minute in the same expensive neighborhood as macOS. Those multipliers mean a cross-platform team concentrates the majority of its spend into a minority of its minutes, and that the highest-return optimization on the hosted side is reshaping where work runs rather than how much of it there is.

We model the break-even point between managed and self-hosted explicitly, because it is the decision most teams get wrong by comparing the wrong numbers. Self-hosting only beats managed when a fleet runs hot nearly all the time, which requires either huge sustained volume or aggressive autoscaling that most teams lack the platform staff to maintain. Managed runners capture the bulk of the raw-compute savings of self-hosting while removing the idle tax and the operations burden, which moves the crossover well in their favor for any team without a fleet that is busy around the clock.

The throughline is that runner economics is a total-cost-of-ownership question, not a per-minute one. The minutes on the invoice are the visible part; the idle capacity, the operations time, the cold starts, and the re-run minutes from transient failures are the larger part that no per-minute comparison captures. The teams that price all of it make better sourcing decisions, and the ones that price only the sticker rate keep concluding that self-hosting is cheap right up until the fully loaded number proves otherwise.

Cost per CI minute by runner type
Linux 2-core$0.008Windows 2-core$0.016macOS$0.08GPU (T4-class)$0.07Managed (Latchkey)$0.0025

Published hosted per-minute rates by OS and accelerator vs a managed alternative. · Source: GitHub Actions pricing + Latchkey rates

Where a self-hosted fleet dollar goes
Active job compute 47%
Idle / between-jobs capacity 28%
Ops & maintenance time 16%
Over-provisioned headroom 9%

Modeled split of monthly spend on an always-on self-hosted runner fleet. · Source: Latchkey analysis (modeled)

Email me the report

The full report is right here on this page, free. Want the link in your inbox to read later or share, plus new Latchkey reports as they drop? Drop your email and we will send it over.

Sent! Check your inbox for the report link.

No spam. Unsubscribe anytime.

The sticker rate is the smallest part of the real cost

Published per-minute rates only cover compute that is actively running a job, which is the part of the cost that is easiest to see and the smallest part of what a self-hosted fleet actually costs. On a self-hosted fleet you also pay for the capacity sitting idle between jobs, the headroom you keep so that peak load does not queue, and the engineering time to operate the whole thing. None of those appear on a per-minute price sheet, and together they often exceed the active-compute cost they sit beside.

The break-even chart prices this directly. A self-hosted Linux fleet at low utilization carries a fully loaded effective cost per useful minute well above the published hosted Linux rate, because every idle minute and every hour of ops time is amortized across the minutes that did real work. Drive utilization high and the self-hosted number drops below the hosted rate, but reaching high utilization is itself the hard part that most teams cannot sustain. The managed bar sits below all of them because it captures the compute savings without carrying the idle and ops load.

The lesson is to compare fully loaded numbers, not sticker rates. A spreadsheet that sets a raw self-hosted instance price against a hosted per-minute rate is comparing the cheapest slice of one model to the entirety of the other, and it reaches a conclusion that the fully loaded math reverses. The effective cost per useful minute, after idle and operations, is the only number that reflects the real decision, and it is the number the break-even chart is built to show.

Effective cost per active minute by sourcing model
Self-hosted (low util)$0.019Self-hosted (high uti…$0.007GitHub-hosted Linux$0.008Managed (Latchkey)$0.0025

Fully-loaded cost per useful minute after idle and ops overhead, modeled for a 40-engineer team. · Source: Latchkey analysis (modeled)

Idle is the silent majority of a self-hosted bill

Runners that are provisioned but waiting for work are still billed by the cloud provider for every minute they exist. CI load is shaped like a workday: heavy during business hours, light overnight and on weekends. A fleet sized to absorb the peak therefore sits largely idle for the majority of the clock, and the modeled split puts a large fraction of paid capacity doing no work on a typical day. That idle capacity is pure cost with no output.

The fleet-dollar split makes the proportions concrete. Active job compute is under half of a typical always-on self-hosted fleet's monthly spend. Idle and between-jobs capacity is the next largest slice, operations and maintenance time is meaningful, and over-provisioned headroom, the extra capacity kept so peak load never queues, adds more on top. More than half of the bill, in this model, goes to something other than running jobs, which is why utilization rather than raw rate is the variable that actually moves a self-hosted budget.

This is the trap that makes self-hosting look cheaper than it is. The team sizes a fleet for peak so developers never wait, the fleet runs idle most of the time, and the idle is invisible because it does not show up as a distinct line item, only as a larger-than-expected total. The only ways out are to autoscale aggressively, which demands platform staff and constant tuning, or to hand the elasticity problem to a runner layer that solves it by construction.

  • Provisioned-but-waiting runners are billed for every minute they exist, output or not.
  • Workday-shaped load leaves a peak-sized fleet idle most of the clock; the modeled idle share is a large fraction of capacity.
  • Active job compute is under half of an always-on fleet's monthly spend; idle, ops, and headroom are the majority.

macOS and GPU dominate cross-platform spend

On the hosted side, the operating system is the dominant cost variable. A macOS minute costs about ten times a Linux minute and a GPU minute is in the same expensive range, while Windows roughly doubles Linux. Those multipliers, ten for macOS and two for Windows against the Linux baseline, are structural, driven by hardware and licensing, and they mean a cross-platform matrix concentrates spend in a way the minute count alone does not reveal.

The monthly-spend split shows the consequence. On a modeled cross-platform team, macOS jobs alone account for the largest share of the bill, with Linux a distant second despite usually running the most minutes, and Windows and GPU filling out the rest. A minority of minutes, the macOS and GPU legs, drives the majority of the dollars. Teams that audit their bills for the first time almost always find this exact shape: the expensive operating systems dominate even when they run the fewest jobs.

The single biggest lever on the hosted side follows directly. Push the heavy, OS-agnostic work, linting, unit tests, dependency resolution, onto Linux where it costs a fraction as much, and reserve macOS, Windows, and GPU for the legs that genuinely need them: signing, packaging, platform UI tests, and accelerated kernels. The expensive runners are frequently doing cheap work that would pass identically on Linux, and reshaping the matrix to stop that commonly removes a third or more of a cross-platform bill with no loss of coverage.

  • macOS is about 10x Linux per minute and Windows about 2x, with GPU near macOS.
  • On a modeled cross-platform team, macOS jobs drive the largest single share of the bill.
  • Moving OS-agnostic work to Linux and reserving premium OSes for platform-specific legs cuts a third or more of spend.
Monthly CI spend by platform mix
macOS jobs 44%
Linux jobs 31%
Windows jobs 16%
GPU jobs 9%

Modeled share of a cross-platform team CI bill before optimization. · Source: Latchkey analysis (modeled)

The per-minute chart understates the gap by leaving out ops

The cost-per-minute chart shows the published hosted rates by OS and accelerator next to the managed rate, and it is the right place to start, but it deliberately omits the cost that makes the self-hosting comparison lopsided. Self-hosted runners add operations cost, patching, scaling, image maintenance, security hardening, and cleanup, that does not appear on any per-minute line. The chart prices the compute; it cannot price the people, and the people are a large part of the self-hosted total.

Read across the chart and the ordering is clear within the hosted tiers: Linux cheap, Windows double, macOS and GPU an order of magnitude higher, and the managed rate below all of them. But the managed advantage is larger than even that gap suggests, because the hosted bars and the managed bar both exclude the same invisible ops axis, and on a self-hosted fleet that axis is substantial. The managed layer is low on the visible per-minute axis and effectively zero on the invisible ops axis at once.

The honest way to use this chart is to read the visible rate and then mentally add the missing axis for any self-hosted option. A self-hosted Linux minute might look competitive with hosted in isolation, but fold in the idle capacity and the operations time from the previous findings and its effective cost climbs well above the bar shown. The managed rate is the only one on the chart that does not have a large hidden cost waiting behind it.

Break-even favors managed below near-constant utilization

The break-even question has a clean answer once it is framed correctly. Self-hosting beats managed only when a fleet runs hot nearly all the time, because high utilization is the only thing that amortizes the idle and ops costs down to where the raw compute advantage survives. Reaching that utilization requires either huge sustained volume that keeps the fleet busy around the clock, or aggressive autoscaling that most teams do not have the dedicated platform staff to build and maintain.

Most teams are nowhere near constant utilization, because their load is workday-shaped and their headcount does not justify a platform group whose job is keeping a runner fleet full. For those teams, the self-hosted effective cost sits at the high end of the break-even chart, above the hosted Linux rate, because the idle and ops overhead never gets amortized away. The model is unambiguous: without near-constant utilization, self-hosting is the more expensive option once it is fully loaded.

Managed runners deliver most of the raw compute savings with none of the idle tax or operations load, which is exactly what moves the crossover. Because a managed layer pools demand across tenants and provisions elastically, it does not pay for a peak-sized idle fleet, and because it operates the runners for you, the ops slice disappears from your side of the ledger. The result is a fully loaded effective cost, modeled at roughly 69% below hosted Linux, that sits below every self-hosted option short of a fleet busy around the clock.

Warm pools and auto-heal recover spend you cannot see on an invoice

Two of the largest recurring costs in CI never appear as a line item, which is exactly why they go unmanaged. Cold starts show up as queue-to-start latency and as developer wait time, not as a charge. Transient failures show up as re-run minutes and as the far more expensive engineer context switch when a green change comes back red for no reason. Both are real money and lost time, and both are invisible to a per-minute comparison that only counts the minutes that ran.

Warm pools attack the first. When a runner is already provisioned and waiting, a job starts in seconds instead of waiting on a cold instance to boot and attach, which removes the queue-to-start latency that pushes developers to over-provision in the first place. The saving is twofold: developers wait less, and the team no longer pads the fleet with idle headroom to hide cold-start delay, so the over-provisioned-headroom slice from the fleet-dollar split shrinks along with the latency.

Automatic recovery of transient failures attacks the second. Most flaky failures are mechanical, a network blip, a registry timeout, an out-of-memory kill, and they pass on a clean retry. Retrying on a fresh environment before a human ever sees a red check removes the wasted re-run minutes and, more valuably, keeps the failure from reaching a developer and breaking their focus. Neither warm pools nor auto-heal show up on a sticker-rate comparison, but both compound into real monthly savings that a naive per-minute analysis misses entirely.

  • Cold-start latency and transient-failure re-runs are real costs that never appear as invoice line items.
  • Warm pools cut queue-to-start latency and shrink the idle headroom teams keep to hide cold starts.
  • Auto-healing transient failures removes wasted re-run minutes and keeps mechanical flakes off developers' screens.

Right-sizing the runner is as important as sourcing it

Sourcing model decides where minutes come from; runner size decides how many you burn. A common and expensive default is to run every job on the largest available runner tier on the theory that bigger is faster, when most jobs are bottlenecked on I/O, network, or sequential test logic rather than on cores. Those jobs finish in nearly the same wall-clock time on a smaller, cheaper runner, so the extra cores are pure cost with no speed benefit.

The right discipline is to match runner size to the job's actual bottleneck. A compile-heavy job that genuinely parallelizes earns a larger runner; a job that waits on a database or a long sequential test does not, and pinning it to a large tier just pays more for the same duration. Measuring where a job spends its time, rather than assuming it is CPU-bound, is what makes right-sizing a real lever instead of a guess.

Right-sizing compounds with the sourcing decision rather than competing with it. A managed runner layer can right-size automatically, matching each job to an appropriate tier instead of defaulting everything to the largest, which captures this saving without anyone hand-tuning a runner matrix. Combined with the Linux-first reshaping, it ensures the minutes you pay for are the minutes you needed at the size you needed.

Recommendations

Price runners fully loaded, never by sticker rate

Compare effective cost per useful minute after idle capacity and operations time, not raw per-minute rates. A self-hosted instance price set against a hosted per-minute rate compares the cheapest slice of one model to the entirety of the other and reaches the wrong answer. The break-even chart's fully loaded numbers are the ones that reflect the real decision.

Treat utilization as the variable that moves a self-hosted budget

Idle, ops, and over-provisioned headroom are the majority of an always-on self-hosted bill; active compute is under half. Self-hosting only wins at near-constant utilization, which needs huge sustained volume or aggressive autoscaling most teams cannot staff. If your load is workday-shaped, the idle tax is structural and self-hosting is the expensive option once loaded.

Reshape the matrix to Linux first

macOS is about 10x a Linux minute and Windows about 2x, and a minority of premium minutes drives the majority of a cross-platform bill. Move OS-agnostic work to Linux and reserve macOS, Windows, and GPU for signing, packaging, platform UI tests, and accelerated kernels. This commonly removes a third or more of the bill with no loss of coverage.

Recover the invisible costs with warm pools and auto-heal

Cold-start latency and transient-failure re-runs are real money that never appears on an invoice. A warm pool cuts queue-to-start latency and lets you stop padding the fleet with idle headroom; automatic recovery of transient failures removes wasted re-run minutes and keeps mechanical flakes off developers' screens. Neither shows on a sticker-rate comparison, but both compound monthly.

Adopt managed runners below near-constant utilization

Managed runners capture the bulk of self-hosted compute savings while removing the idle tax and the operations load, targeting roughly 69% below hosted Linux on a fully loaded basis. For any team without a fleet busy around the clock and the platform staff to keep it that way, the break-even sits firmly in managed's favor.

Outlook

Expect runner economics to stay a total-cost-of-ownership story rather than a per-minute one, and expect the teams that internalize that to keep pulling ahead. The visible minutes on the invoice are not where the waste lives; the idle capacity, the operations time, the cold starts, and the re-run minutes are, and none of them respond to shopping for a slightly cheaper sticker rate. The durable savings come from removing those hidden costs, which is a sourcing and architecture decision, not a procurement one.

The OS-multiplier structure is not going to soften, because it reflects real hardware and licensing costs that both platforms and self-hosters share. That makes the Linux-first reshaping a permanent lever rather than a one-time cleanup, and it means cross-platform teams will keep concentrating spend into a minority of premium minutes until they reshape where the work runs. The teams that treat the matrix as something to optimize continuously will keep that spend in check; the ones that let it accrete will keep overpaying for cheap work on expensive runners.

For most teams the practical conclusion is that the break-even line sits in managed's favor and stays there unless a fleet is busy around the clock with staff to keep it full. Price the runners fully loaded, reshape the matrix to Linux, recover the invisible cold-start and re-run costs with warm pools and auto-heal, and source the minutes from a layer that removes the idle and the operations entirely. The organizations that do this turn CI compute from an opaque, growing line item into a managed and predictable one.

Methodology

This report combines published CI runner and cloud GPU pricing with Latchkey's own modeling of fleet utilization and fully loaded cost. Per-minute hosted rates and the OS multipliers reflect published GitHub Actions pricing; the GPU per-minute figure is anchored to published cloud rates for a T4-class accelerator. Figures labeled modeled, including fleet idle share, the fleet-dollar split, the effective-cost break-even, and the platform-mix spend split, are illustrative estimates derived from public pricing, typical workday-shaped load, and representative team sizes, not a primary survey. Modeled figures are intended to show direction and magnitude rather than a precise population value. Figures labeled "modeled" are illustrative estimates derived from public pricing and typical pipeline shapes, not a primary survey; figures attributed to a named source reflect that source. Pricing reflects published rates at time of writing and should be verified against current provider pricing.

Sources

More Latchkey reports

See what you would save with Latchkey managed runners and self-healing. Start free →