What’s new in Bazel 6.0

Also posted on BuildBuddy Blog

Bazel 6.0 includes over 3,100 changes since 5.4.[1] It’s the latest major release, following the release of 5.0 in January of this year, and it’s Bazel’s third LTS release.

Since there were so many changes, many of them quite impactful, I felt I needed to review them all and provide a nice summary for y’all. Similar to Bazel 5.0’s changes, the end result was quite big, so I’ve included a table of contents to allow easy navigation to the changes that interest you the most:

Command-line flag changes

Bazel’s LTS strategy allows for breaking changes between major versions. In particular, it allows for command-line flags to be removed, renamed, made to do nothing, or have their default values changed. In the following sections I collected all such flag changes I could find.


Default Values Changed



These flags now do nothing, but still exist to allow for migration off of them:



One of Bazel’s most powerful features is its ability to use remote caching and remote execution. Numerous improvements and fixes to Bazel’s remote capabilities are included in Bazel 6.0.

Remote caching (RBC)

Using a remote cache is one of the most popular ways of speeding up a Bazel build. Thankfully these changes make using a remote cache both more performant and more reliable:

Remote execution (RBE)

For some projects, using remote execution is the ultimate performance unlock for their Bazel builds. In addition to the remote caching changes covered above, which also apply to remote execution, the following changes improve the remote execution experience:

Dynamic execution

Dynamic execution allows for Bazel to race remote and local execution of actions, potentially allowing you to get the benefit of both modes, without the drawbacks of either. Bazel 6.0 included a number of changes to dynamic execution, almost all of them behind new experimental flags:

Local execution

In buck2, local execution is a specialization of remote execution. So I’m going to use that as the reason that this section is listed under the “Remote” section, and not because I don’t want to reorganize this post just to fit in a couple neat local execution changes 😉:

Build Event Service (BES)

Using a build event service can give you unparalleled insight into your Bazel builds at scale. There were some nice changes to BES support, though I think the improvements to how it interacts with the remote cache are especially noteworthy.


Bazel offers various methods to gain insight into your build. I cover some of the notable changes to those methods below.

Build Event Protocol (BEP)

The build event protocol is used by build event services, so all of these changes could have also been listed in that section as well. The BEP can also be collected locally with --build_event_json_file and --build_event_binary_file.

The vast majority of changes added additional information to the BEP, though some are fixes and improvements:

Timing profile

The action timing profile, which is enabled by default with --profile, is viewable both locally in Chrome and on build event services. These changes add more detail and clarity to the profile:

Execution log

Bazel logs all of the spawns it executes in the execution log, which is enabled with the --execution_log_json_file or --execution_log_binary_file flags. This feature is relatively stable, with just a few noticeable additions:


bazel build wasn’t the only command to get improvements in this release. Here are some changes that were made to the query family of commands:



Dependency management

A new dependency system named Bzlmod was added in Bazel 5.0, and made non-experimental in Bazel 6.0. Besides all of the changes needed to support Bzlmod, these were some other notable dependency management related changes:

Platforms and toolchains

The C++, Android, and Apple rules are being migrated to support building with Platforms. While progress has been made, they don’t fully support it yet in Bazel 6.0. For C++ projects, it’s recommended that the --incompatible_enable_cc_toolchain_resolution flag is used, to help the Bazel team discover any issues in the wide variety of projects that exist.

Here are some of the platforms and toolchains related changes which weren’t tied to any of those migrations:

Execution platforms

Execution platforms are platforms which build tools execute on. These include the host platform on which Bazel runs.

In the following sections I collected notable changes for Linux and macOS. I’m sure there were some for Windows as well, but since I don’t use Bazel on Windows, none of the changes stood out to me as pertaining only to it.



Target platforms

Target platforms are platforms which you are ultimately building for. I cover the Android and Apple platforms in the following sections, as they still have some functionality provided by Bazel core, instead of being fully supported by standalone Starlark rules.




While there are lots of programming languages that are supported through standalone Starlark rules, some are still written as “native” rules in Bazel core, or are bundled Starlark rules while Starlarkification is in progress. In the following sections I summarize the notable changes in support of these languages.

C and C++




Rules authoring

Bazel’s extensibility is powered by the ability to write custom rules. Most rules used in a project will be provided by open source rule sets, but projects may also define rules themselves. Bazel 6.0 includes numerous changes that make custom rules more performant, easier to write, or even expand what is possible to do with them.


Aspects allow augmenting build dependency graphs with additional information and actions. These changes expanded their capabilities:

Persistent workers

Persistent workers improve build performance by sending multiple requests to long-running processes. Here are some notable changes to persistent worker support:


As mentioned at Bazelcon, progress is being made on migrating natives rules out of Bazel and into standalone Starlark rules. In the Bazel 6.0 release progress was made on the Android, C++, Java, Objective-C, Protobuf, and Python rules.

In addition to changes directly needed for Starlarkification, for which there were many and I’m not going to list them here, the Starlark language itself received performance and feature improvements:


There were a handful of changes that I couldn’t find a nice home for in the sections above, but I still felt were important or interesting enough to call attention to:


As you can see, Bazel 6.0 was another massive release. Thankfully, through the rolling releases process, people were able to test, or even actively depend on, these changes well before the first 6.0 release candidate was cut.

I expect Bazel 6.1 to be a fast follow with some changes that missed the final release candidate. Work on Bazel 7.0 is well underway as well, and I look forward to summarizing its changes next year.

  1. The GitHub UI shows some commits that already exist in the 5.x series of releases due to cherry-picking, so the number of unique commits is actually smaller, closer to 2,800. ↩︎