Skip to content
Latchkey
Published June 2026 by Daniel Zoghalchali

The State of Bazel in CI 2026

Remote cache, remote execution, hermetic builds, and the adoption curve: where the cache-hit payoff actually lives and what makes it leak away.

83%
median action cache hit rate on a healthy warm Bazel pipeline (modeled)
Latchkey analysis (modeled)
7.8x
CI speedup at a high cache hit rate vs a from-scratch build (modeled)
Latchkey analysis (modeled)
14%
of teams report using Bazel or a Bazel-family build system
JetBrains Developer Ecosystem Survey

Executive summary

Bazel's promise is simple to state and hard to deliver: describe your build hermetically once, and never do the same work twice. A correct, content-addressed action graph means any output produced anywhere can be reused everywhere, so a warm pipeline only builds what genuinely changed. At a high cache hit rate, that turns a multi-thousand-action build into a handful of cache lookups, and a build that takes fifteen minutes from scratch finishes in a couple. It is one of the few build-system ideas that genuinely changes the economics of CI rather than shaving the edges.

The catch is that the entire payoff is a function of cache hit rate, and hit rate is fragile in ways that are easy to underestimate. Bazel only reuses an action's output if the action's inputs hash identically to a previous run, and anything that perturbs that hash, a non-declared input, a drifting toolchain, a timestamp baked into an output, invalidates the action and everything downstream of it. A single leaky rule near the root of the graph can cascade into rebuilding a large subtree that should have been free.

This report quantifies the cache-hit payoff curve and shows how steep and unforgiving it is. Below a certain hit rate the overhead of hermeticity and remote coordination can leave a team slower than a simpler build tool, while above it the speedup compounds dramatically. It also breaks down where hits leak, why remote execution only pays once the cache is warm, where teams land on the adoption curve by org size, and why the whole machine depends on a runner layer that can keep a shared cache warm and co-located.

The adoption data tells its own story. Bazel usage rises sharply with engineering org size, because the fixed cost of writing and maintaining hermetic build definitions only amortizes across a large, shared codebase. Small teams rarely clear the break-even; large monorepos clear it decisively. The adoption curve therefore looks less like a technology preference and more like a function of how much duplicated build work an organization has to eliminate before the hermeticity tax pays for itself.

The most important practical finding is that a warm shared cache is a runner problem, not a Bazel problem. Bazel can describe a perfect action graph, but it cannot keep the remote cache warm, co-locate it with the runners, or absorb the transient network failures that would otherwise force a cold rebuild. Those are infrastructure responsibilities, and a team that nails the build definitions but runs them on a cold, distant, flaky cache will watch its hit rate, and its entire investment, collapse.

CI build time vs action cache hit rate
0% hit (cold)940 s50% hit520 s80% hit244 s95% hit121 s

Wall-clock for a large hermetic build as the remote action-cache hit rate rises. · Source: Latchkey analysis (modeled)

Build time by execution strategy
Local, no cache940 sLocal + remote cache244 sRemote execution162 sRemote exec + warm ca…98 s

Modeled wall-clock for the same target graph across execution strategies. · 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 cache-hit rate is the only number that matters

Bazel's entire value proposition collapses to one metric: what fraction of actions hit the cache rather than re-executing. The payoff curve is dramatic at the top end, a large build at a 95 percent hit rate finishes roughly 7.8 times faster than from scratch, but it is steep and unforgiving below that. The hit-rate chart shows the wall-clock falling sharply as the rate climbs, which means every percentage point of hit rate is worth real time.

The danger zone is the bottom of the curve. Below roughly a 50 percent hit rate, the overhead that Bazel imposes, hashing every input, coordinating with a remote cache, enforcing hermeticity, can leave a team slower than a simpler build tool that just compiles everything and moves on. Bazel is not free when it misses; it pays a coordination tax on every action whether or not the cache helps, so a low hit rate gets the tax without the benefit.

The strategic consequence is that essentially all Bazel investment should target hit rate above every other concern. Faster runners, more cores, and bigger worker pools all matter far less than keeping the cache warm and the build hermetic, because those determine where on the steep curve a team lands. A team optimizing anything other than hit rate is polishing a number that the hit rate dominates.

  • A 95 percent hit rate yields roughly a 7.8x speedup; the curve is steep, so each point is worth real time.
  • Below about 50 percent hit, Bazel's coordination overhead can make it slower than a simpler build tool.
  • Hit rate dominates every other lever, so it is where investment should concentrate.

Hermeticity violations are where hits leak

Most avoidable cache misses trace back to a small set of causes, and the leak breakdown names them: non-hermetic inputs are the largest slice, followed by a cold cache after a reset, toolchain drift between runners, and volatile data like timestamps baked into outputs. Each of these is a way the action hash changes when the meaningful inputs did not, so Bazel correctly concludes it has never seen this action and rebuilds it.

The reason violations are so costly is the cascade. The action graph is a tree of dependencies, so a leak near the root invalidates every action beneath it, not just itself. A single build rule that quietly reads an undeclared file, a clock, an environment variable, the system's installed compiler version, can turn what should have been a near-total cache hit into a partial rebuild of a large subtree. The blast radius of one leak is the whole subtree under it.

Closing these is the highest-leverage work on a maturing Bazel pipeline, and it is mostly a matter of discipline rather than infrastructure. Declare every input explicitly, pin toolchains so they do not drift between runners, and strip volatile data like timestamps from outputs. The hermeticity-loss chart is effectively a prioritized to-do list: fix the largest slices first, because they are where the most hits are leaking.

  • Non-hermetic inputs are the single largest source of avoidable cache misses.
  • A leak near the root of the action graph invalidates its entire subtree, not just one action.
  • The fixes are discipline: declare inputs, pin toolchains, strip timestamps from outputs.
Why cache hits are missed
Non-hermetic inputs 41%
Cold cache after reset 28%
Toolchain drift 19%
Timestamp / volatile data 12%

Estimated split of avoidable cache misses on a maturing Bazel pipeline. · Source: Latchkey analysis (modeled)

Remote execution only pays once the cache is warm

Remote execution fans out actions across a worker pool so that many run in parallel on remote machines rather than serially on the local runner. But it shares the same content-addressed cache, so its benefit stacks on top of cache hits rather than replacing them. The execution-strategy chart shows the fastest configuration is remote execution feeding off a warm cache, well ahead of remote execution alone.

Run against a cold cache, remote execution mostly pays coordination overhead for work that should never have run. The whole point of the cache is to avoid executing actions whose outputs already exist, so fanning those actions out to a worker pool to re-execute them is paying twice: once to coordinate the fan-out, once to redo work a warm cache would have skipped entirely. Remote execution accelerates the misses, but a warm cache eliminates them, and eliminating beats accelerating.

The correct sequencing follows directly. Get the cache warm and the build hermetic first, so the hit rate is high, and only then add remote execution to parallelize the genuine misses that remain, the small fraction of actions that actually changed. A team that adds remote execution before fixing hit rate is optimizing the wrong layer, throwing parallelism at work that should have been a cache lookup.

Adoption is an org-size phenomenon

Bazel adoption rises sharply with engineering org size, and the adoption-by-size chart shows the climb clearly: low single digits at small teams, rising steeply through the hundreds of engineers, and reaching its peak at the largest orgs. With roughly 14 percent of teams overall reporting Bazel or a Bazel-family build system, the headline number understates how concentrated that usage is among large organizations.

The driver is amortization. The fixed cost of writing and maintaining hermetic build definitions is substantial, and it only pays off when spread across a large, shared codebase with enough duplicated build work to eliminate. A small team builds a small graph that a simpler tool handles fine, so the hermeticity tax never earns back its cost. A large monorepo rebuilds the same shared libraries thousands of times, so eliminating that duplication is worth the upfront work many times over.

The adoption curve therefore looks less like a technology preference and more like a function of how much duplicated build work an org has to eliminate. This is useful framing for a team deciding whether to adopt Bazel at all: the question is not whether Bazel is good but whether the codebase is large and shared enough that the hermeticity investment amortizes. Below that threshold, a simpler tool with a warm cache is usually the better economics.

Bazel adoption by org size
<20 eng4%20-100 eng11%100-500 eng23%500+ eng38%

Share of teams using Bazel or a Bazel-family build system, by engineering org size. · Source: Latchkey analysis (modeled)

Cold-cache resets quietly undo a warm pipeline

A cold cache after a reset is the second-largest source of missed hits in the breakdown, and it is the one most directly tied to the runner layer rather than the build definitions. A perfectly hermetic build still goes cold every time the cache it depends on is empty, which happens after an eviction, a cache wipe, a region change, or simply running on a runner that cannot reach the warm cache fast enough.

This is insidious because it is invisible in the build files. A team can fix every hermeticity violation, declare every input, and pin every toolchain, and still see its hit rate sag because the cache keeps going cold underneath an otherwise correct build. The build is right; the infrastructure starves it. No amount of build-definition discipline addresses a cache that is not there when the action looks for it.

The remedy is a persistent, co-located, adequately sized cache that survives between runs and sits close enough to the runners to serve hits quickly. That is squarely a runner-layer responsibility, which is why this finding bridges the hermeticity work above and the runner-layer argument below. A warm build needs a warm cache, and keeping the cache warm is not something the build graph can do for itself.

A warm shared cache is a runner problem, not a Bazel problem

Bazel can describe a perfect action graph, but it cannot keep your remote cache warm, co-locate it with your runners, or absorb the transient network failures that would otherwise force a non-hermetic cold rebuild. Those are all infrastructure responsibilities that live in the runner layer, and they are exactly the responsibilities that determine where on the steep payoff curve a team actually lands.

On a managed runner with a warm, co-located cache, the hit rate stays high run to run rather than sagging after every eviction, which keeps the build near the top of the payoff curve where the 7.8x speedup lives. The compute also lands around 70 percent cheaper than hosted rates, so the minutes a high hit rate already saves are cheaper per minute on top of being fewer, compounding the economics in the team's favor.

The runner layer also closes the reliability gap that hermeticity opens. A flaky remote-cache connection or a transient network failure can force Bazel to treat a cached action as a miss and rebuild it, undoing the hit. Auto-healing retries absorb those transient remote-cache and network failures on a fresh environment before they become a cold rebuild, which protects the hit rate from exactly the mechanical failures that hermeticity discipline cannot prevent. The payoff and execution-strategy charts both show that warm-cache configuration as the fastest one in the report.

  • Keeping the cache warm, co-located, and reachable is a runner responsibility the build graph cannot fulfill.
  • A managed warm cache keeps hit rate near the top of the curve and runs around 70 percent cheaper per minute.
  • Auto-healing retries absorb transient cache and network failures that would otherwise force a cold rebuild.

Bazel without a warm cache is the worst of both worlds

It is worth stating the failure case plainly, because it is common and avoidable. A team that adopts Bazel for its caching promise but runs it on a cold or distant cache gets the full hermeticity tax, the input hashing, the strict input declaration, the coordination overhead, without the payoff that justifies the tax. That is the worst position on the payoff curve: all of the cost, none of the speed.

This is how Bazel earns its reputation for being slow and complicated among teams that have tried it and given up. The complexity is real, but it is only worth paying for at a high hit rate, and a high hit rate requires a warm cache that those teams never had. They experienced Bazel at the bottom of the curve, concluded it was slower than their old tool, and were not wrong about their configuration even though they were wrong about Bazel.

The corrective lesson ties the whole report together. Bazel is not a build tool you adopt; it is a caching system you operate, and the operation, warm cache, hermetic inputs, co-located runners, reliable network, is where the value is won or lost. A team that treats the cache as infrastructure to keep warm gets the 7.8x; a team that treats Bazel as a drop-in compiler replacement gets the tax. The difference is the runner layer, not the build files.

Recommendations

Optimize hit rate above every other lever

The payoff curve is steep, so each point of cache hit rate is worth real wall-clock, while faster cores and bigger pools matter far less. Measure hit rate as your primary Bazel metric and treat a drop in it as a build-breaking regression, because it directly determines where on the curve your builds land.

Close hermeticity violations in order of blast radius

Non-hermetic inputs are the largest source of leaked hits, and a leak near the root of the graph invalidates its whole subtree. Declare every input explicitly, pin toolchains so they do not drift between runners, and strip timestamps and other volatile data from outputs, fixing the largest leak categories first.

Warm the cache before adding remote execution

Remote execution accelerates cache misses, but a warm cache eliminates them, and eliminating beats accelerating. Get hit rate high first, then add remote execution to parallelize only the genuine misses that remain, rather than fanning out work a warm cache would have skipped.

Run on a persistent, co-located cache

A cold cache after a reset undoes an otherwise hermetic build, and it is a runner-layer problem the build files cannot fix. Use a persistent cache that survives between runs and sits close to the runners, so hermetically correct actions actually find their outputs instead of rebuilding them.

Decide adoption on codebase size, not hype

The hermeticity investment only amortizes across a large, shared codebase with substantial duplicated build work. If your org is below the threshold where the adoption curve climbs, a simpler build tool with a warm cache is usually the better economics, and Bazel's tax will not earn back its cost.

Outlook

Expect the runner layer to become the center of the Bazel conversation over the next two years, displacing the build-definition focus that has dominated it. As more teams discover that hermeticity discipline alone does not deliver the payoff without a warm, co-located cache, the differentiator shifts from how well a team writes BUILD files to how well its infrastructure keeps the cache warm and reachable. The build files are necessary; the runner layer is what makes them pay.

Adoption will likely stay concentrated at the large end of the org-size curve rather than democratizing downward, because the underlying economics do not change: the hermeticity tax only amortizes across a large shared codebase. What may shift is the floor, as managed runner layers that ship a warm co-located cache lower the operational burden of keeping hit rate high, a few more mid-size monorepos may clear the break-even that today only large orgs reach. But Bazel will remain a large-codebase tool, not a default.

For teams already committed to Bazel, the durable takeaway is to treat it as a caching system to operate rather than a build tool to install. The 7.8x speedup at the top of the curve is real and worth pursuing, but it is bought with warm caches, hermetic inputs, and reliable runners, not with the build graph alone. The teams that internalize that will spend the period near the top of the payoff curve, while the ones that treat Bazel as a drop-in compiler keep paying the tax at the bottom of it.

Methodology

This report combines public Bazel and build-systems ecosystem data, including the JetBrains Developer Ecosystem Survey signal that roughly 14 percent of teams use Bazel or a Bazel-family build system, with Latchkey's own analysis of CI runner economics. Cache-hit curves and execution-strategy timings are modeled on a representative large hermetic build and will vary with action-graph shape, cache locality, and worker-pool size. Adoption figures by org size are modeled from public developer-survey signals on build-tool usage and indicate direction rather than precise population values. Cost figures derive from published GitHub-hosted per-minute rates and the Latchkey managed rate, roughly 70 percent below the hosted blend. 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 → 30-day trial · No credit card