This is our Style Guide for Protobuf.
This document is purposefully concise, and is meant as a short reference for developers to refer to when writing Protobuf schemas.
The requirements follow
DEFAULT lint category. For details on each checker and
it's rationale, see that documentation. Within this Style Guide, we provide
links under (Why?) where relevant for each check.
The recommendations are not enforced, but are rather for reference. Some of
the recommendations will be incorporated into the
This Style Guide is designed to provide consistency and maintainability across a Protobuf schema of any size and any purpose, but without being so opinionated as to restrict organizations from making the design decisions they need to make for their individual APIs. We will provide a Strict Style Guide for those who want a set of rules to provide further consistency across their Protobuf schema. This will include items like file ordering, documentation, and field naming.
Files and Packages
All files should have a package defined. (Why?)
All files of the same package should be in the same directory. All files should
be in a directory that matches their package name. (Why?)
For example, assuming we have a single root
Packages should be
The last component of a package should be a version. (Why?)
Files should be named
The following file options should have the same value, or all be unset, for all files that have the same package: (Why?)
For example, if we have file
foo_two.proto with package
foo.v1 must have these three options
set to the same value, and the other options unset:
No imports should be declared as
Enums should not have the
allow_alias option set. (Why?)
Enum names should be
Enum value names should be
Enum value names should be prefixed with the
UPPER_SNAKE_CASE of the enum name.
(Why?). For example, given the enum
enum value names should be prefixed with
The zero value for all enums should be suffixed with
(Why?) The suffix is configurable
for Buf linting. For example, given the enum
FooBar, the zero value should be
FOO_BAR_UNSPECIFIED = 0;.
Message names should be
Field names should be
Oneof names should be
Field names should not be any capitalization of "descriptor", with any number of prefix or suffix underscores. (Why?). For example, all of the following should not be field names:
Service names should be
Service names should be suffixed with
Service. (Why?) The
suffix is configurable for Buf linting.
RPC names should be
All RPC request and responses messages should be unique across your Protobuf schema. (Why?)
All RPC request and response messages should be named after the RPC, either by naming them
While not strictly related to style, set up breaking change detection and do not break your Protobuf schema. See the breaking change detector documentation for more details on how to enforce this with Buf.
// instead of
/* */ for comments.
Over-document, and use complete sentences for comments. Put documentation above the type, instead of inline.
Avoid widely-used keywords for all types, especially packages. For example, if your
package name is
internal component will block importing
the generated stubs in other packages for Golang.
Files should be ordered in the following manner (this matches Google's current recommendations):
- License header (if applicable)
- File overview
- Imports (sorted)
- File options
- Everything else
Used pluralized names for repeated fields.
Name fields after their type as much as possible. For example, for a field of message
FooBar, name the field
foo_bar unless there is a specific reason to do otherwise.
Avoid using nested enums and nested messages. You may end up wanting to use them outside of their context message in the future, even if you do not think so at the moment.
While controversial, our recommendation is to avoid streaming RPCs. While they certainly have specific use cases that make them extremely valuable, on the whole they generally cause a lot of problems, push RPC framework logic up the stack, and usually prevent developing more reliable architectures.