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:
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 whenbreaking.useis omitted frombuf.yaml.PACKAGE: Detects breakage to generated source code on a per-package basis. More lenient thanFILEbecause 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#
- Quickstart: Set up breaking change detection in a sample project.
- Usage guide: Configuration options and invocation patterns.
- Rules and categories: Every rule, grouped by category.
- BSR breaking change checks: Enforcing breaking change policy on the registry.