This document describes how to configure and use a local disk cache for Bazel artifacts in your Fuchsia development environment.

## Overview

The Fuchsia build system uses Bazel for building certain parts of the system. By default, Bazel stores its cache inside the build directory (e.g., `out/default/bazel-*`). If you clean your build directory (for example, by running `fx clean-build` or `rm -rf out`), this cache is lost, and Bazel must rebuild everything from scratch.

You can configure a persistent, shared disk cache that survives build directory cleans and can be shared across multiple Fuchsia checkouts and/or build directories on the same machine.

## Benefits of a shared disk cache

- **Faster Clean Builds:** When you run a clean build, Bazel can retrieve previously built actions and artifacts from the disk cache instead of rebuilding them.

- **Shared Across Checkouts:** If you work with multiple Fuchsia checkouts on the same machine, they can all share the same disk cache. Artifacts built in one checkout can be reused in another, saving time and disk space.

- **Shared Across Build Directories:** If you switch between different build directories in the same checkout, actions that are identical between them (including input contents) will automatically benefit from the cache too.

- **Shared Across Branches:** If you frequently switch between branches, while using the same build directory, incremental builds will also benefit from the disk cache.

- **Complements Remote Caching (RBE):** Bazel's disk cache is compatible with remote caching. Even when Remote Build Execution (RBE) is enabled, a local disk cache is often faster because it avoids network latency when retrieving cached artifacts. It also allows you to work offline for targets you have already built.

## Enabling the Bazel disk cache

To enable the disk cache, set the `FUCHSIA_BAZEL_DISK_CACHE` environment variable to an **absolute path** of a directory where you want to store the cache.

For example, add the following line to your shell startup script (e.g., `~/.bashrc` or `~/.zshrc`):

    export FUCHSIA_BAZEL_DISK_CACHE="$HOME/.fuchsia_bazel_cache"

The build system will automatically create the directory if it does not exist.

> [!TIP]
> **Tip:** Place the cache directory on the **same filesystem** as your Fuchsia checkouts. This allows Bazel to use hard-links or reflinks (on supported filesystems) to reference cached artifacts, which significantly reduces disk space usage and improves build performance.

> [!IMPORTANT]
> **Important:** The path specified in `FUCHSIA_BAZEL_DISK_CACHE` must be an absolute path. Relative paths will cause the build to fail.

## Managing cache size (Garbage Collection)

By default, the disk cache will grow indefinitely. To prevent it from consuming too much disk space, you can enable automatic garbage collection by setting the `FUCHSIA_BAZEL_DISK_CACHE_SIZE` environment variable.

This variable specifies the maximum size of the cache. Bazel will periodically clean up older cached items in the background when it is idle to stay under this limit.

Add the following line to your shell startup script, specifying the desired limit (e.g., `40G` for 40 Gigabytes):

    export FUCHSIA_BAZEL_DISK_CACHE_SIZE="40G"

The size can be specified in bytes, or optionally followed by `K`, `M`, `G`, or `T`.

If `FUCHSIA_BAZEL_DISK_CACHE_SIZE` is not set, you must manage the cache size manually (e.g., by deleting the directory contents when it grows too large).

## Avoiding caching for large artifacts

Caching is not always beneficial; for example, for targets that generate large artifacts which change often, such as product assembly. Bazel provides several ways to avoid caching these artifacts.

For individual target definitions, the [`tags` attribute](https://bazel.build/reference/be/common-definitions#common-attributes), common to all rules, can be used. For example:

    genrule(
        name = "create_large_archive",
        ...

        # No need to run this remotely, nor cache the archive.
        tags = ["no-cache", "no-remote"],
    )

For custom rules, the implementation function should invoke `ctx.actions.run()` with an `execution_requirements` attribute set to a dictionary mapping tag strings to the string literal `"1"`. Note that using `True` or the integer `1` will not work, which is not properly documented. For example:

    def _my_rule_impl(ctx):
        ...
        ctx.actions.run(
            ...,
            execution_requirements = {
                "no-cache": "1",
                "no-remote": "1",
            },
        )
        ...

    my_rule = rule(
        implementation = _my_rule_impl,
        ...
    )

In this case, all `my_rule()` target artifacts will automatically not be cached (or remoted).
[](https://issues.fuchsia.dev/issues/new?component=1439230&template=1881640&description=Issue+on:+https://fuchsia.dev/docs/development/build/bazel_disk_cache.md "Report a bug or suggest improvements on this page") [](https://cs.opensource.google/fuchsia/fuchsia/+/main:docs/development/build/bazel_disk_cache.md "View the source code of this page") [](https://ci.android.com/edit?repo=fuchsia/fuchsia/main&file=docs/development/build/bazel_disk_cache.md&cloneRepo=fuchsia/fuchsia:refs/heads/main&fullPath=fuchsia/docs/development/build/bazel_disk_cache.md "Edit the source code of this page")