Troubleshooting guide

How to improve build cache hit rate: diagnosis and fixes

A low remote cache hit rate is usually an input-quality problem, not a storage problem. This guide shows how to reproduce one miss, compare its key inputs across machines, fix the causes that matter, and avoid the more dangerous failure: stale hits from a key that is missing required inputs.

Measure the right hit rate

Split local hits, remote hits, and misses by task. Then weight them by cold execution time. Ten remote hits on a six-minute compile matter more than hundreds of hits on a one-second formatting task. Compare equivalent branches and warmed time windows so first-run population does not distort the result.

Correctness comes first. A suspiciously high hit rate can mean the key omits an environment variable, toolchain version, or source input that changes the output. Every optimization must preserve the rule: same key means interchangeable output.

Diagnose one miss end to end

Choose one expensive task that should have hit, then reproduce it from the same commit in two clean environments:

1. Pin the same build-tool and runtime versions.
2. Run the task once and record its hash, inputs, outputs, and environment.
3. Run it on the second machine with the same source revision.
4. Compare the first differing input.
5. Fix that category and repeat until the keys match.

Do not start by deleting caches. A cache clear proves only that a miss can execute; it does not explain why two equivalent builds produced different keys.

The common causes of cache misses

  • Over-keying: documentation, tests, or unrelated global files invalidate production builds.
  • Environment drift: CI and laptops use different runtimes, flags, paths, locales, or declared variables.
  • Volatile values: timestamps, build numbers, temporary paths, and runner IDs enter the key.
  • Non-deterministic outputs: generated ordering, random seeds, or embedded dates change identical builds.
  • Output mistakes: required files are undeclared, so a hit restores only part of the result.
  • Fragmented cache scope: machines authenticate to different workspaces or provider namespaces.

Tool-specific checks

Nx: inspect inputs, namedInputs, runtime inputs, and declared outputs. Use production filesets so specs and docs do not invalidate builds.

Turborepo: review task inputs, env, globalEnv, and globalDependencies; use run summaries to compare hashes.

Gradle: confirm the task is cacheable, inspect --info, align JDK and Gradle versions, and remove absolute-path or machine-specific inputs.

Bazel: compare action inputs, execution platform, toolchain, flags, and environment. Undeclared host reads are both a cache-rate and correctness problem.

Hit-rate improvement checklist

  • Pin runtime, package manager, compiler, and build-tool versions.
  • Declare every output-changing environment value and exclude irrelevant volatile values.
  • Narrow task inputs without omitting correctness-critical files.
  • Make generated outputs reproducible across machines.
  • Confirm all clients use the same remote endpoint and workspace.
  • Track time saved after each change, not just the headline percentage.

For Nx-specific examples, continue with tuning Nx inputs and outputs.

Related guides

Measure which tasks miss and what they cost
Cachely turns cache operations into per-project hit-rate and time-saved insights.
Start freeSee pricing
FAQ

Build cache hit rate: frequently asked questions

What is a good build cache hit rate?
There is no universal target. A lower hit rate on expensive tasks can save more time than a high hit rate on cheap tasks. Track weighted time saved alongside hit rate, and compare equivalent branches, task types, and time windows.
Why is my remote build cache hit rate low?
Common causes are inputs that are too broad, environment or toolchain drift between machines, timestamps or random values in outputs, undeclared or incorrectly declared outputs, and CI variables that change on every run.
How do I diagnose a cache miss?
Re-run the same task from the same commit in two clean environments, compare the input hashes and declared outputs, then remove differences one category at a time: source files, dependency graph, environment, runtime version, flags, and global configuration.
Can a cache hit rate be too high?
Yes, if required inputs are missing from the key. An incorrectly high hit rate can replay stale outputs. Optimize only after correctness: every value that can change the result must participate in the key.
Should I measure local and remote hits separately?
Yes. Local hits show same-machine reuse; remote hits prove work is shared across CI and developers. Ephemeral CI runners should produce a meaningful share of remote hits after the cache is warm.