Skip to content
Latchkey
Published June 2026

The 2026 CI Queue Time Benchmark

A baseline for how long jobs actually wait before they start, broken out by runner type and pipeline load, and exactly what a warm pool removes from cold-start delay.

42 s
median cold-start wait before a fresh runner picks up a job
Latchkey analysis (modeled)
88%
of cold-start wait removed when a warm pool serves the job
Latchkey analysis (modeled)
76%
of professional developers run CI on every push, so queue time is paid often
Stack Overflow Developer Survey

Executive summary

Queue time is the part of CI nobody bills you for directly but everybody feels. Before a single line of a job runs, the runner has to exist and register with the control plane, and on cold-start fleets that provisioning gap stacks on top of whatever queue depth the pipeline already carries at peak load. The meter does not start until the first step executes, so this wait is invisible on the invoice. It is entirely visible, though, in cycle time, in context switching, and in the quiet friction of waiting for a check that has not even begun.

This benchmark separates the two costs that get conflated under the word queue. The first is pure scheduling queue, the time a job spends waiting for a slot when the fleet is saturated. The second is the cold-start provisioning penalty, the time spent standing a runner up before it can take any job at all. We model pure queue wait by runner type and by pipeline load, then isolate the provisioning penalty and show precisely what a warm pool removes from it.

The result is consistent across fleet shapes. A warm pool collapses the typical cold-start wait to near zero because the expensive part, provisioning, has already happened before the job arrives. Under burst load a warm pool combined with prompt overflow provisioning keeps the tail from blowing out, while the cheaper Linux runners still carry most of the work. The latency benefit and the cost benefit point at the same architecture rather than trading off against each other.

Because CI adoption sits near 76 percent of professional developers and most of those teams run CI on every push, queue time is paid extraordinarily often. A wait that looks trivial per job, tens of seconds, multiplies into hours of aggregate developer idle time per week once it lands on every push from every contributor. The benchmark frames queue time as a recurring tax precisely because its per-instance smallness is what lets it hide while it accumulates.

Median job wait by runner type
Cold-start hosted42 sSelf-hosted idle18 sManaged warm pool5 sAlways-on dedicated3 s

Modeled time from job queued to job started, by runner provisioning model. · Source: Latchkey analysis (modeled)

Wait time as pipeline load rises
Light (1-5 jobs)38 sModerate (6-20)61 sHeavy (21-50)104 sBurst (50+)156 s

Modeled median wait at increasing concurrent-job load on a cold-start 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.

Provisioning, not the scheduler, dominates cold-start wait

The intuitive culprit for queue time is the scheduler, the assumption being that jobs wait because something is deciding what to dispatch. The benchmark says otherwise. On a cold-start fleet the largest slice of pre-run wait by far is spinning up the instance and registering the runner, not the scheduler choosing a job. The scheduler queue is the smallest slice in our model; provisioning and registration together dominate it.

This matters because it tells you which fixes work and which do not. Throwing a bigger or faster scheduler at the problem addresses the smallest slice. Adding more runner capacity helps only at saturation, and even then each new runner pays its own provisioning penalty before it can help. The actual delay lives in standing a runner up from nothing, which is work that has to happen before any job runs and which no amount of scheduling cleverness removes.

The structural fix follows directly from the decomposition. If the expensive part is provisioning, then the answer is to do the provisioning before the job arrives rather than after. That is precisely what a warm pool is: a set of runners already booted, already registered, already imaged, waiting to be handed a job. The cold-start split is, in effect, a list of exactly the work a warm pool front-loads off the critical path.

  • Instance provisioning and runner registration are the two largest slices of cold-start wait.
  • Scheduler queue is the smallest slice; faster scheduling barely moves the total.
  • A warm pool front-loads provisioning, registration, and image warmup before the job arrives.
Where cold-start wait goes
Instance provisioning 46%
Runner registration 27%
Image + tool warmup 18%
Scheduler queue 9%

Modeled split of the pre-run wait on a cold-start runner. · Source: Latchkey analysis (modeled)

A warm pool collapses the typical wait to near zero

When a pre-registered runner is already waiting, the job starts almost immediately and the provisioning penalty simply disappears. The modeled median wait drops from forty-two seconds on a cold-start hosted fleet to about five seconds on a managed warm pool, within a couple of seconds of always-on dedicated runners but without paying for dedicated capacity around the clock.

The reason the collapse is so large is that a warm pool removes the dominant slices rather than trimming a small one. Because provisioning and registration are most of the wait, eliminating them by doing them ahead of time removes most of the wait. What remains is a near-trivial handoff: assign the queued job to a runner that is already booted and listening. That is why the warm-pool bar in the by-runner chart sits down with always-on rather than partway down from cold-start.

This saving is paid back on every push, which is what makes it consequential rather than incidental. A one-time forty-second saving would not matter. A forty-second saving repeated on every push across a busy repository with many contributors is a different quantity entirely, recovered continuously for as long as the pool exists. The benchmark frames the warm pool not as a latency trick but as the removal of a recurring tax.

Wait time blows out under burst load on cold fleets

Light load hides the queue problem; burst load exposes it brutally. At one to five concurrent jobs a cold-start fleet looks tolerable, because the small number of provisioning events overlap and the wait stays in the tens of seconds. As concurrent jobs climb past the fleet's standing capacity, the wait grows non-linearly, because each overflow job has to pay its own provisioning penalty from scratch rather than slotting into existing capacity.

In our model the median wait roughly quadruples from light to burst load on a cold fleet, climbing from under forty seconds to over two and a half minutes. This is the regime that hurts most, because burst load is exactly when the team most needs CI to be responsive: a coordinated merge window, a release crunch, a morning where everyone pushes at once. The fleet is slowest precisely when it is busiest, which is the worst possible coupling.

A warm pool combined with prompt overflow provisioning keeps the tail bounded instead of letting it starve. The pool absorbs the first wave instantly, and overflow jobs cold-start promptly rather than queuing behind a slow scale-up. The benchmark's point is not that cold-start never happens under a warm pool, it is that the warm pool plus fast overflow keeps the burst tail from exploding into the multi-minute waits that a pure cold-start fleet produces under the same load.

  • Cold-start median wait roughly quadruples from light load to burst load in the model.
  • Each overflow job past standing capacity pays its own provisioning penalty.
  • Burst load coincides with merge windows and releases, when responsiveness matters most.

Queue time is paid on every push, so it compounds

Because the large majority of professional teams run CI on every push, even a modest per-job wait multiplies into hours of developer idle time per week. The arithmetic is unforgiving: a team merging a few hundred times a week, each merge preceded by several pushes, each push triggering checks that wait tens of seconds to start, accumulates a wait budget measured in hours that never appears on any bill.

The cost is invisible on the invoice but very visible in cycle time and context switching. A developer who pushes a small change and waits a minute for the check to even start is a developer who tabs away, loses the thread, and returns minutes later having paid a context-switch cost far larger than the wait itself. Queue time is corrosive precisely because it is small enough to tolerate individually and frequent enough to dominate in aggregate.

This is why queue time deserves to be measured and budgeted like any other CI metric rather than shrugged off as unavoidable. With adoption near 76 percent and CI on every push, the per-push wait is one of the most-repeated operations in the entire engineering workflow. Shaving it is one of the highest-frequency improvements available, and a warm pool shaves the largest part of it on every single one of those pushes.

Managed warm pools cut wait without paying for always-on

Always-on dedicated runners deliver low wait, but they do it by paying for idle capacity around the clock. A runner that sits booted and registered all night so that morning jobs start fast is a runner you paid for all night. For a team with predictable, constant load that can be acceptable; for the spiky load that CI actually produces, it means paying peak prices for trough utilization.

A managed warm pool captures most of the latency benefit of always-on while billing closer to actual usage. The pool keeps enough runners warm to absorb normal load and starts fast, but it scales with demand rather than sitting permanently provisioned at peak size. The run minutes are billed at the managed rate, well below the hosted Linux price, so the team gets near-dedicated responsiveness without the dedicated-capacity bill.

This is the balance most teams without a platform group actually want. Self-managing a warm pool means continuously tuning its size against demand, patching its images, and absorbing the idle cost of whatever buffer keeps it responsive. A managed layer does that tuning automatically and prices the result at roughly 69 percent below hosted, which is why the warm-pool line in the cost chart sits at the bottom while still delivering the near-instant pickup the wait charts show.

Runner cost per minute by type
Linux 2-core$0.008Windows 2-core$0.016macOS$0.08Managed warm pool$0.0025

Published GitHub-hosted per-minute rates vs the Latchkey managed warm-pool rate. · Source: GitHub Actions pricing + Latchkey rates

Self-hosted idle runners are a partial, expensive answer

Between cold-start hosted and a managed warm pool sits the self-hosted idle runner, and the benchmark places its wait squarely in the middle. A self-hosted runner that is already up and registered avoids the worst of the provisioning penalty, so its median wait is meaningfully better than cold-start hosted. But it does not reach warm-pool latency, because a single idle runner saturates the moment a second concurrent job arrives, at which point everything behind it pays full provisioning again.

The hidden cost of the self-hosted idle approach is that the responsiveness it does deliver is bought with permanently running compute and continuous operational attention. The runner that is idle and waiting is a runner the team pays for while it waits, and keeping it patched, secured, and healthy is standing engineering work. It is the same trade as always-on dedicated, scaled down to a small fleet, which means it inherits both the idle cost and the ops burden without fully solving the wait.

This is why the self-hosted idle line is a cautionary middle rather than a destination. It demonstrates that pre-provisioning helps, which is the whole thesis of the warm pool, but it does so in the most labor-intensive and least elastic way available. A managed warm pool generalizes the same insight, pre-provisioning to remove wait, while adding the elasticity and the automated operations that the hand-run idle fleet lacks.

  • Self-hosted idle wait sits between cold-start hosted and a managed warm pool in the model.
  • A lone idle runner saturates at the second concurrent job, sending overflow back to full provisioning.
  • It inherits idle compute cost and ops burden without reaching warm-pool latency or elasticity.

Wait time is the metric developers feel before any other

Of all the CI metrics a team can track, queue time is the one developers experience first and most viscerally. A long pipeline is at least visibly doing something; a job stuck in queue is doing nothing, and the developer staring at a check that has not started has no signal that anything is happening at all. The absence of progress is more corrosive to focus than slow progress, which is why even modest queue time generates outsized frustration.

This perception gap means queue time shapes behavior in ways its raw seconds understate. Developers who learn that checks take a while to even start begin batching their pushes, holding changes back to avoid waiting, which works directly against the small-batch, push-often discipline that fast delivery depends on. The wait does not just cost the idle seconds; it nudges the whole team toward larger, riskier changes to amortize a delay they have come to expect.

Removing the wait therefore pays a behavioral dividend on top of the time saved. When a pushed change starts validating almost immediately, pushing small and often stops feeling expensive, and the team drifts back toward the cadence that keeps changes easy to review and easy to revert. A warm pool's near-instant pickup is, in this sense, not only a latency improvement but a quiet correction to the incentives that long queue time distorts.

Recommendations

Measure queue time as a first-class CI metric

Track time from job queued to job started, separately from job duration, and alert when it regresses. Because queue time is paid on every push and never appears on the invoice, it goes unmanaged unless it is explicitly instrumented. A team that cannot see its wait cannot defend against its slow accumulation.

Attack provisioning, not the scheduler

The dominant slices of cold-start wait are instance provisioning and runner registration, not scheduling. Do not invest in scheduler tweaks or bigger runners to fix wait; front-load the provisioning with a warm pool so the expensive work happens before the job arrives rather than on the critical path.

Size a warm pool to normal load and let overflow cold-start

Keep enough runners warm to absorb typical concurrency so the common case starts in seconds, and rely on prompt overflow provisioning for bursts. This bounds the burst tail without paying for always-on capacity sized to the worst case, which is the worst-utilized way to buy responsiveness.

Plan for burst windows explicitly

Wait time blows out under burst load because each overflow job pays its own provisioning penalty, and bursts coincide with merge windows and releases when responsiveness matters most. Ensure overflow provisioning is fast enough that burst jobs cold-start within a tick rather than starving in the queue behind a slow scale-up.

Prefer a managed warm pool over self-tuned always-on

Always-on runners cut wait by paying for idle capacity around the clock against load that is actually spiky. A managed warm pool delivers near-dedicated pickup while billing run minutes at roughly 69 percent below hosted and scaling with demand, which is the right balance for any team without a dedicated platform group.

Outlook

Expect queue time to graduate from an unmeasured annoyance to a tracked metric through 2026, sitting alongside pipeline duration on engineering dashboards. As more teams instrument the gap between queued and started, the warm-pool advantage will become legible in numbers rather than anecdote, and the cold-start fleet will increasingly look like an avoidable default rather than a fact of CI life.

The burst regime is where the next round of differentiation happens. Light-load wait is already tolerable on most fleets; it is under coordinated merge windows and release crunches that cold-start fleets fall apart, and that is exactly when responsiveness is most valuable. Warm pools paired with fast overflow provisioning will become the expected way to keep the burst tail bounded, because the alternative is a fleet that is slowest precisely when the team needs it most.

The durable conclusion is that the latency story and the cost story converge on the same architecture. A managed warm pool removes the dominant slices of cold-start wait while billing run minutes well below hosted rates, so a team does not have to choose between fast pickup and a reasonable bill. Over the next two years we expect that convergence to make the self-managed cold-start fleet the harder position to defend.

Methodology

This benchmark models CI job wait time across runner provisioning models (cold-start hosted, self-hosted idle, managed warm pool, always-on dedicated) and pipeline load levels, and prices the run minutes against published GitHub Actions runner rates (Linux 0.008, Windows 0.016, macOS 0.08 per minute, with OS multiples of Linux 1x, Windows 2x, macOS 10x). Queue and cold-start latencies and the wait-component split are Latchkey modeled estimates labeled as such; the managed line uses the Latchkey rate of 0.0025 per minute, a 69% reduction versus the blended hosted average. CI adoption near 76% is from the developer survey. 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 →