2.4.3 What Makes a Cache Hit
A cache hit in Bazel means more than "the file already exists." Bazel asks whether a specific action is the same computation as before: the same declared inputs, the same instructions for producing outputs, and the same relevant execution context. When that identity matches, Bazel can safely reuse outputs instead of rerunning the action.1,2,3
Cache hits are action-level
That boundary lives below the top-level target. One target often expands into several actions: compiles, archives, links, code generators, test runners. Bazel caches the resulting artifacts, not "the fact that //app:server ran", which is the artifact-based model from P.2.1 Task-Based vs Artifact-Based.3,4
A Make-style mental model is too weak here. Task-based systems mostly reason from tasks and file timestamps, so command or environment changes are easy to miss. Bazel records the action definition itself, which is why changing compiler options or other configuration can invalidate work even when the source files did not change.5,6
That is why building the same label under different configurations can legitimately produce different compile or link outputs. The label may be the same, but the action definition is not.1,5
What goes into the key
For Level 2, use a three-part checklist: inputs, instructions, and execution context.
- Inputs: declared source files and generated files consumed by the action. Remote caching works because Bazel knows those inputs explicitly and can reuse outputs only when the same input state is seen again.2,7
- Instructions: the command line and other action metadata that define what tool Bazel is asking to run.1,4
- Execution context: build flags, action environment variables, and target platform are part of configuration. Tools and toolchain files participate separately because Bazel treats tools as dependencies too.1,3
The internal names you may meet later
If you inspect bazel dump --action_cache in 5.7 Cache & Execution, you will see names like actionKey, usedClientEnvKey, and digestKey. You do not need to memorize them for Level 2. The useful point is that Bazel tracks non-file metadata, environment, and file digests separately when deciding whether an on-disk output is still valid.7
Why hermeticity decides whether the key is trustworthy
A normal cache miss only costs time. A false cache hit is worse, because it reuses the wrong bytes. That is why hidden inputs are dangerous: if an action depends on host state Bazel did not record, the key no longer fully describes the real computation.8
There are two practical leak paths worth calling out. Environment variables can reduce cross-machine hits when different machines smuggle different values into an action definition, and tools outside the workspace can produce different outputs even though Bazel did not track the tool itself as an input.2 Real cache-miss investigations show the same pattern with $PATH, host compilers, and non-deterministic files generated by repo rules or package managers.9,10
That is the bridge back to 2.3.1 Hermeticity. Hermeticity is not a separate optimization from caching. It is what makes the cache key meaningful in the first place. When a build keeps rebuilding unexpectedly, 2.4.4 Diagnosing Cache Misses is the first-response tool at this level. When you later need action-by-action proof, 5.7 Cache & Execution is the deeper debugging chapter.2,8
A cache hit means Bazel proved "same action, same result," not just "same target name" or "newer file." Think in terms of declared inputs, command/config/env, and tools: change any of those, and a rebuild is usually correct. Leave them stable and Bazel can safely reuse outputs across commands, checkouts, and even machines.1,2,3
Check your understanding · 3 questions
1.A developer changes only compiler flags, not any source files. Should Bazel reuse cached action outputs from the previous build?
Select one answer
2.Which factors are included in Bazel's action cache key?
Select all that apply
3.True or false: cache key correctness and hermeticity.
Choose True or False for each sentence
Footnotes
-
Bazel Glossary — definitions of action, action key, action cache, and configuration ↩1 ↩2 ↩3 ↩4 ↩5
-
Remote Caching — action inputs, output names, command line, environment, Action Cache lookup, and env/tool leakage caveats ↩1 ↩2 ↩3 ↩4 ↩5
-
Artifact-Based Build Systems — artifact-based model and treating tools as dependencies ↩1 ↩2 ↩3 ↩4
-
Bazel and action (non-) determinism — one target expanding into multiple actions and action identity as command, input hashes, and environment configuration ↩1 ↩2
-
Build programs with Bazel — correct incremental rebuilds depend on matching inputs and command/config, not only file freshness ↩1 ↩2
-
Task-Based Build Systems — timestamp/task model and why command or environment changes are easy to miss ↩
-
The Many Caches of Bazel — output-tree
actionKey,usedClientEnvKey,digestKey, and remote Action Cache lookup ↩1 ↩2 -
Hermeticity — hidden inputs, host-state leaks, and why reproducibility underpins caching ↩1 ↩2
-
Diagnosing Bazel Cache Misses — non-deterministic repository rule outputs becoming downstream inputs and causing misses ↩
-
.bazelrc flags you should enable —
$PATHand other environment leaks causing large cache misses ↩