Thanks to visit codestin.com
Credit goes to buf.build

Skip to content

Detecting breaking changes#

buf breaking compares the current version of your Protobuf schema against a past version and reports any changes that would break clients, servers, or the code generated from those schemas. The past version can be any input the Buf CLI accepts: a BSR module, a Git repository, a tarball, or a Buf image.

For example, changing a field’s type from int32 to string:

Before
message User {
  int32 id = 1;
}
After
message User {
  string id = 1;
}

Running buf breaking against the previous version flags the change:

$ buf breaking --against '.git#branch=main'
user.proto:2:3:Field "1" on message "User" changed type from "int32" to "string".

Tag 1 now carries an incompatible wire type, so every existing client and every serialized message already in flight becomes unreadable. Catching this before merge is the point.

See the quickstart for a hands-on walkthrough.

How compatibility is defined#

Protobuf schemas break at different layers. Adding a new field is safe at every layer. Renaming an existing field breaks generated source code but leaves the wire format intact. Changing a field’s type breaks everything.

buf breaking groups its rules into four categories, from strictest to most lenient:

  • FILE: Detects breakage to generated source code on a per-file basis. Important for languages with file-specific generated imports like C++ or Python. Default when breaking.use is omitted from buf.yaml.
  • PACKAGE: Detects breakage to generated source code on a per-package basis. More lenient than FILE because moving a definition between files in the same package doesn’t break consumers that import the package as a whole.
  • WIRE_JSON: Detects breakage to the binary wire format or JSON encoding.
  • WIRE: Detects breakage to the binary wire format only.

Passing a stricter category implies passing every looser one: schemas that pass FILE also pass PACKAGE, WIRE_JSON, and WIRE. Pick the category that matches what your consumers actually depend on. A schema consumed only over the wire can tolerate WIRE; a schema whose Go generated code is depended on externally needs PACKAGE.

See rules and categories for the full list of rules in each category.

Where breaking change detection runs#

Three places, covering the lifecycle from authoring to production:

  • Locally. Run buf breaking --against <past-version> from the command line while you work.
  • In CI. The same command fits into any pipeline. Buf ships a GitHub Action; the CI/CD integration guide covers other common setups. Failures surface as PR comments next to the lines that introduced them.
  • On the BSR. Server-side breaking change checks catch anything CI missed. When a developer pushes a module that would break consumers, the push enters a review flow where repository owners approve or reject the change before it reaches production.

Customizing the rules#

The built-in rules and categories cover the common cases. For organization-specific policies, enable or disable individual rules in buf.yaml, or bring your own rules through Buf check plugins. See the usage guide for configuration examples.

Further reading#