layout: documentation title: Backward compatibility category: getting-started

Backward Compatibility

This page provides information on how to handle backward compatibility, including migration requirements and how to communicate incompatible changes. It also covers policy information and guidelines to follow these policies.

Bazel is evolving, and changes will be made to Bazel that at times will be incompatible and require some changes from Bazel users.

GitHub labels

At a glance

  1. Every breaking change is guarded with an --incompatible_* flag.
  2. Newly introduced incompatible flags default to off.
  3. For every --incompatible_* flag, there is a GitHub issue that explains the change in behavior and provides a migration recipe.
  4. The migration window is at least one release long and is set by the author of the incompatible change.
  5. APIs and behavior guarded by an --experimental_* flag can change at any time.
  6. Users should never run their production builds with --experimental_* or --incompatible_* flags.

How to follow this policy

What is stable functionality?

In general, APIs or behaviors without --experimental_... flags are considered stable, supported features in Bazel.

This includes:

  • Starlark language and APIs
  • Rules bundled with Bazel
  • Bazel APIs such as Remote Execution APIs or Build Event Protocol
  • Flags and their semantics

Incompatible changes and migration recipes

When a release contains an incompatible change, the Bazel team provides migration windows and migration recipes to make it easier for Bazel users to update their code.

Migration window is one or more release of Bazel during which a migration from old functionality to new functionality is possible, according to a migration recipe.

During the migration window, both the old and new functionality are available in the Bazel release. For every incompatible change, a migration recipe is provided that allows updating the user code (BUILD and .bzl files, as well as any Bazel usage in scripts, usage of Bazel API, and so on) in such a way that it works simultaneously without any flags with old and new functionality.

In other words, during a migration window for an incompatible change foo:

  1. --incompatible_foo flag is available in Bazel release and defaults to off.
  2. User code can be updated in such a way that it works simultaneously with that flag being on or off.
  3. After the code is migrated, the users can check whether they migrated successfully by building with --incompatible_foo=true. However, their code will continue to work in the same release in default state (where --incompatible_foo is off), as well after the migration window is over (at which point the flag will be effectively on).

Communicating incompatible changes

The primary source of information about incompatible changes are GitHub issues marked with an “incompatible-change” label.

For every incompatible change, the issue specifies the following:

  • Name of the flag controlling the incompatible change
  • Description of the changed functionality
  • Migration recipe

The incompatible change issue is closed when the incompatible flag is flipped at HEAD.

All the incompatible changes for which a Bazel release X.Y is part of a migration window are marked with a label “migration-X.Y” label (for example migration-0.21).

All the incompatible changes that are expected to happen in release X.Y are marked with a label “breaking-change-X.Y” (for example breaking-change-0.21).