Configure Bazel Remote Cache

Last updated: July 21, 2026

Why Bazel Remote Cache

A Bazel remote cache lets a team of Engineers, AI Agents and Continuous Integration (CI) system share build outputs across machines. When builds are reproducible, outputs from one machine can be safely reused on another machine, it can make builds significantly faster, up to 90% in real projects. Bazel breaks a build into discrete steps called actions. Each action has declared inputs, list of output filenames, a command line, and environment variables.

The remote cache stores an Action Cache (AC) for build action metadata and a Content-Addressable Store (CAS) for actual output file. One Bazel AC entry can reference many CAS entries. Bazel can resolve both AC and CAS across developer workstations, CI, and AI Agent environments.

Since Bazel 7, it runs in "Build without the Bytes" mode by default, where Bazel can skip download of most of CAS entries, they can be really heavy, in the build action graph and only resolve AC entries (kilobytes). "Build without the Bytes" is critical for best Bazel performance and BuildFetch Cache is uniquely optimized to serve these entries as fast as possible through its In-Memory → NVMe → SSD tiered storage system.

BuildFetch Cache correctly preserves Bazel AC → CAS relations when it evicts entries via LRU GC. This is critical for build correctness and avoids common Bazel build error scenario when Remote Cache hits AC entry but then misses on related CAS entries.

CI can use --config=ci to read and upload results. Developers and AI agents can use--config=dev to read from the same cache without uploading new entries.

Instead of recompiling, retesting, and repackaging on every machine, Bazel retrieves cached action outputs from the remote cache and reports them as remote cache hit in the build summary — turning work that takes minutes into cache lookups that finish in seconds or even milliseconds.

After CI populates the Remote Cache, a build on another machine can resolve most expensive actions from cache. In a typical scenario:

First build (CI populates the remote cache — ~10 minutes):

Bash
$ bazel build //... --config=ci

INFO: Analyzed 45 targets (12 packages loaded, 234 targets configured).
INFO: Found 45 targets...
INFO: 45 processes: 45 internal.
INFO: Build completed successfully, 45 total actions in 10m 4s

Subsequent build (developer, AI agent, or fresh CI agent — ~4 seconds):

Bash
$ bazel build //... --config=dev

INFO: Analyzed 45 targets (0 packages loaded, 0 targets configured).
INFO: Found 45 targets...
[1/45] //dto:protobuf - cache hit
[2/45] //auth:lib - cache hit
[3/45] //api:lib - cache hit
...
INFO: 45 processes: 2 internal, 43 remote cache hit.
INFO: Build completed successfully, 45 total actions in 4s

Remote Bazel caching is especially valuable in ephemeral CI environments where CI agents are recreated on every run, and in actively developed monorepos where CI continuously warms the shared cache for the whole team. For safe sharing across machines, keep action inputs reproducible — for example, whitelist environment variables with --action_env so differing $PATH values do not reduce cache hit rates.

Configure Bazel Remote Cache

Official Bazel Remote Caching documentation: https://bazel.build/remote/caching.

Keep remote cache flags in .bazelrc. Use named configuration groups to separate CI read-write access from developer read-only access:

.bazelrc
build --remote_cache=https://token-auth:<TOKEN>@<CACHE_HOST>/<PROJECT_ID>/bazel/
build --remote_timeout=30

build:ci --remote_upload_local_results=true
build:dev --remote_upload_local_results=false

On CI, you can provide credentials through environment variables, for example:

Bash
export BUILDFETCH_BAZEL_REMOTE_CACHE_HOST="cache.example.buildfetch.com"
export BUILDFETCH_BAZEL_PROJECT_ID="project-id"
export BUILDFETCH_BAZEL_REMOTE_CACHE_TOKEN="..."
export BUILDFETCH_BAZEL_REMOTE_CACHE_URL="https://token-auth:${BUILDFETCH_BAZEL_REMOTE_CACHE_TOKEN}@${BUILDFETCH_BAZEL_REMOTE_CACHE_HOST}/${BUILDFETCH_BAZEL_PROJECT_ID}/bazel/"

bazel build //... --config=ci --remote_cache="${BUILDFETCH_BAZEL_REMOTE_CACHE_URL}"

For developer access, you can use a local token source (for example a shell profile or secret manager) and run Bazel with --config=dev so local builds read from cache without uploading:

Bash
export BUILDFETCH_BAZEL_REMOTE_CACHE_HOST="cache.example.buildfetch.com"
export BUILDFETCH_BAZEL_PROJECT_ID="project-id"
export BUILDFETCH_BAZEL_REMOTE_CACHE_TOKEN="..."
export BUILDFETCH_BAZEL_REMOTE_CACHE_URL="https://token-auth:${BUILDFETCH_BAZEL_REMOTE_CACHE_TOKEN}@${BUILDFETCH_BAZEL_REMOTE_CACHE_HOST}/${BUILDFETCH_BAZEL_PROJECT_ID}/bazel/"

bazel test //... --config=dev --remote_cache="${BUILDFETCH_BAZEL_REMOTE_CACHE_URL}"