Ensuring Bazel Cache Hits: Hermeticity Over Source Identity
Unexpected Bazel cache misses usually stem from a lack of hermeticity—relying on undeclared environment variables or host specifics. Explicitly declare all dependencies using <code>execution_requirements</code>. Learn configuration and verification steps.
07 Oct 2025, 00:06 UTC

The Core Problem: Cache Misses Despite Identical Source Code
In large Bazel setups utilizing Remote Build Execution (RBE) and remote caching, the most common reason for unexpected cache misses is not a change in source code, but a violation of hermeticity—the principle that an action’s output depends only on its declared inputs, not on the environment it runs in. The useful takeaway is that you must explicitly declare all external dependencies, including environment variables and toolchain properties, via execution_requirements.
Configuring Remote Execution for Scale
To leverage RBE, configure your .bazelrc file. This directs Bazel to offload heavy compilation and testing to a remote cluster (like Buildbarn or Buildfarm) rather than running everything locally.
build --remote_executor=grpc://rbe.example.com:443 --remote_cache=grpc://rbe.example.com:443 --remote_instance_name=my-project- For secure access with GCP services, include authentication:
--tls_enabled=true --oauth_token=$(gcloud auth print-access-token)
Enforcing Hermeticity with Execution Requirements
Bazel derives cache keys from command lines, input file digests (SHA‑256), and declared environment variables. If an action implicitly relies on an undeclared variable (e.g., $PATH or $HOME), Bazel treats it as non‑hermetic, leading to a cache miss even if the source files haven’t changed.
Consider this example where a build script relies on a specific system path:
# In a relevant platform definition or BUILD file context
execution_requirements {
key: \"os-family\"
value: \"linux\"
}
execution_requirements {
key: \"container-image\"
value: \"my-builder:latest\"
}
# If the script unexpectedly uses an env var not listed above, the cache fails.Operational Limits and Pitfalls
Bazel itself does not manage the Time‑To‑Live (TTL) for remote cache entries; this is a configuration managed entirely by the remote service (e.g., setting max_age_seconds in Buildbarn’s CAS configuration). Furthermore, relying on host‑specific features (like specific temporary directory layouts or user namespaces) will cause flakiness because remote workers run in isolated containers.
Practical Verification: Run a build while logging the explanation: bazel build //... --remote_executor=... --remote_cache=... --explain=explain.log. Inspect explain.log for actions tagged remote-cache-hit versus remote-executed to validate caching effectiveness.
Limitation: Network egress costs can be significant; monitor remote service metrics (e.g., Buildbarn’s CAS size) to ensure retention policies are correctly configured to prevent unbounded storage growth.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.