3.6.4 Disk Cache in CI
--disk_cache is the cheapest way to make a cold CI runner less wasteful: persist one directory across runs, and Bazel can reuse action results even though the server process itself starts empty every time.1,2 It works best when the same machine or restored volume survives between jobs. Once many stateless workers need to share the same outputs, you are already leaving the "local disk" world and moving toward 3.6.5 Simple Remote Cache Setup.1,3
What Bazel stores in the disk cache
The key mental model from 2.4 Caching & Incrementality still applies here: Bazel is not caching "the build succeeded", it is caching concrete action results. The disk cache uses the same two-store model as remote cache infrastructure: an Action Cache (ac/) keyed by the action digest, and a Content Addressable Store (cas/) keyed by content hash.2 On a hit, Bazel can reconstruct the outputs from that cache instead of re-running the action.
That is why --disk_cache helps even when CI jobs are separate Bazel invocations. The in-memory server state from 3.6.2 Bazel Server Lifecycle in CI is gone, but the external cache directory is still there, so successful actions can be reused across jobs, after bazel shutdown, and even after bazel clean.2,3
When disk cache is enough
Disk cache is the right first step after 3.6.1 Basic CI Recipe when reuse happens on one runner or through the CI platform's directory restore/save mechanism.3 The line is clear: stateful workers benefit from local repository and disk caches on their own filesystem, while stateless workers lose those local caches when the machine is replaced and therefore need a shared remote cache instead.3
That boundary matters because --disk_cache is still local state. It reduces repeated execution work, but it does not solve cross-runner sharing. If the same commit lands on different workers and you expect all of them to see the same cached outputs, go to 3.6.5 Simple Remote Cache Setup rather than trying to treat one machine's disk as team-wide infrastructure.1,3
Put the path behind a named CI config
This is a 3.2 Project Configuration concern, not something every CI step should spell out inline. The core flag is:
build:ci --disk_cache=/path/to/build/cache
The important part is not the exact directory name. The important part is that the path is stable and points to a location your CI system actually persists between runs.1 For developer machines, ~ can be used in the path and is expanded by Bazel, which makes a checked-in .bazelrc practical when the same cache pattern should apply outside CI as well.1 Use an explicit --disk_cache=<path> in shared presets. Current Bazel docs also describe boolean-style forms such as --disk_cache / --disk_cache=true for the default location and --nodisk_cache / --disk_cache=false to disable.1 The ci-cache-baseline .bazelrc wires the flag with an explicit path, build:ci --disk_cache=~/.cache/bazel-disk, alongside a --repository_cache line on the same build:ci block.
Trace: A CI preset imports a shared .bazelrc that sets build --disk_cache=/cache/bazel-disk. A particular job tries to "clear" it by appending build:ci --nodisk_cache. Did that disable disk cache?
Reveal
Yes. Because .bazelrc lines accumulate and the last value for a flag wins, the later disabling form overrides the inherited path and turns the cache off.1
This is a real CI footgun in reverse: a later rc layer can silently undo the shared cache preset. If a job should opt out, do it deliberately with a documented disabling line. If it should stay on, inspect --announce_rc output and make sure no later layer overrides the cache flag.
Growth is the operational catch
The biggest downside of disk cache in CI is not correctness, but growth. Every newly cached action adds more files, so a long-lived runner can eventually trade faster builds for a full disk if nothing bounds the cache.1 Built-in garbage-collection flags address this: starting with Bazel 7.4, --experimental_disk_cache_gc_max_size and --experimental_disk_cache_gc_max_age can cap the cache, and Bazel runs that cleanup while idle between builds.1
If you are not ready to rely on those flags, the fallback is operational: clean the cache directory explicitly or move to a cache service that owns retention for you.1,3 That is one of the natural transition points from local disk cache to 3.6.5 Simple Remote Cache Setup: not just sharing across machines, but also wanting cache lifecycle management that is no longer "some directory on a runner".
When --disk_cache and --remote_cache are both set
Once both flags are enabled, Bazel uses a combined cache rather than treating them as two unrelated features.4 The surprising part is worth spelling out: the pair behaves like remote cache overall, unless --incompatible_remote_results_ignore_disk is set, in which case the disk cache keeps acting like a local cache even when remote accept/upload flags are turned off.4
That is a real configuration edge, but it is already "simple remote cache" territory, not the core of this article. If your normal CI config mixes both layers, finish this chapter for the local-disk mental model, then continue with 3.6.5 Simple Remote Cache Setup.
--disk_cache is the first CI cache worth adding because it needs no extra service: just one persistent directory and a stable build:ci config. It shines on one runner or on CI platforms that restore the same directory between jobs. Once cache policy becomes about branch strategy, periodic clean runs, and resilience under failure, the next layers are 3.6.6 Cache Warm/Cold Considerations and 6.6 Build Service Operations.
Check your understanding · 3 questions
1.A CI platform restores a disk cache directory before each job and saves it afterward. The runner is ephemeral (destroyed after each job). What does --disk_cache provide in this setup?
Select one answer
2.True or false about disk cache behavior and management:
Choose True or False for each sentence
--disk_cache=<path> so cache location and persistence are obvious.3.When is a local disk cache the right choice vs. a remote cache?
Select one answer
Footnotes
-
Remote Caching and Command-Line Reference —
--disk_cacheas an opt-in filesystem-backed external cache, checked-in.bazelrcusage with the~alias, boolean-style enable/disable forms, and disk-cache GC flags ↩1 ↩2 ↩3 ↩4 ↩5 ↩6 ↩7 ↩8 ↩9 ↩10 -
The Many Caches of Bazel — disk cache as local AC/CAS, with visible
ac/andcas/directories and action-digest-based reuse ↩1 ↩2 ↩3 -
How Bazel built its CI system on top of Buildkite — stateful workers benefiting from local disk cache, stateless workers needing remote cache, and reuse surviving separate jobs ↩1 ↩2 ↩3 ↩4 ↩5 ↩6
-
Bazel's Remote Caching and Remote Execution Explained — combined-cache behavior when
--disk_cacheand--remote_cacheare enabled together ↩1 ↩2