Type & path uniqueness policy enforcement for enterprises
Authored by Patrick Mitchell
Avoiding name conflicts between Protobuf types in an application is critical to service stability, as failing to do so
will result in fatal runtime exceptions and outages. Preventing these failures can prove challenging due to the fact
that these conflicts may be introduced by other module dependencies despite your own code being flawless, such as when
multiple libraries provide their own copies of
google.type.Timestamp. A detailed example is available later in this
To solve this issue and improve application stability for our customers, we’re introducing a new feature in the BSR that allows customers on our Enterprise plan to enforce uniqueness of Protobuf types and file paths across all modules:
- Prevent outages caused by type conflicts: Eliminate the risk of runtime exceptions and subsequent outages caused by including conflicting Protobuf type names or file paths.
- Preclude Protobuf file vendoring: Reject pushes to modules that copy and redeclare types such as those in
googleapis, and ensure that there is one source of truth for every Protobuf schema across your instance.
Enforce type uniqueness in the BSR
BSR administrators can enforce this policy across their entire instance. To enable it, they first need to execute a scan to determine whether there are any existing collisions between types that have already been pushed to the BSR:
This scan will identify and list each collision so that administrators can coordinate with API owners to resolve any outstanding issues:
Once the collisions have been identified and resolved, administrators can enable uniqueness enforcement. The BSR will then reject any pushes that introduce new collisions, and the CLI will display an error. More information can be found in our documentation.
Example of Protobuf type conflicts in Go
Protobuf runtimes require that type declarations be universally unique, and having two types with the same name will
result in a fatal runtime exception in many languages. As an example, consider two teams at a company which each define
their own versions of a
company.profiles.UserProfile message in two different modules since they each require different
fields to display.
If a third team wants to aggregate information from both of the other teams' APIs and subsequently includes both of these types in their Go server, this would result in a runtime panic:
panic: proto: file "profiles/v1/profile.proto" has a name conflict over company.profiles.UserProfile previously from: "company.buf.team/gen/go/team1/profileinfo/protocolbuffers/go/profiles/v1" currently from: "company.buf.team/gen/go/team2/profiledetails/protocolbuffers/go/profiles/v1"
Had the BSR’s type uniqueness policy been enabled, it would not have been possible for each team to declare their own
version of the
company.profiles.UserProfile type. This policy encourages engineers to be specific, ideally resulting in
descriptive names such as
Get started with type uniqueness enforcement
To enable type uniqueness enforcement in the BSR, go to your admin settings or take a look at our documentation. If you aren’t on our Enterprise plan today, you can check out our pricing plans. As always, feedback and questions are welcome in the Buf Slack!