Buf Schema Registry (BSR)

Go packages

The Buf Schema Registry provides generated SDKs for Go from modules and plugins using go get, just like any other Go library. It generates SDKs automatically when you push schema changes, which eliminates the need to manage a Protobuf toolchain or generate code locally.

See the tutorial for instructions on how to access generated SDKs from the BSR directly.

The BSR Go module proxy implements the GOPROXY protocol for Buf modules by generating SDKs on the fly—Go code stubs aren't generated until you request them using go get. Once generated, they're cached, and the cached SDKs are returned from subsequent requests.

Using Go modules

The key to consuming from the BSR Go module proxy is choosing the right Go module path. The import path for generated Go code has this format:

Go module path syntax
Examplebuf.build/gen/go/connectrpc/eliza/connectrpc/go
Legend:
constant{variable}

In this example, buf.build/gen/go/connectrpc/eliza/connectrpc/go, the BSR generates code for the connectrpc/eliza module using the connectrpc/go plugin. This SDK depends on buf.build/gen/go/connectrpc/eliza/protocolbuffers/go as well—connect-go has a dependency on code generated by the protocolbuffers/go plugin, and generated SDKs automatically include plugin dependencies.

Installing SDKs

To generate the connectrpc/eliza Protobuf module using the connect-go plugin, you could install the generated SDK like this:

$ go get buf.build/gen/go/connectrpc/eliza/connectrpc/go
Output
go: downloading buf.build/gen/go/connectrpc/eliza/connectrpc/go v1.11.0-20230727062025-d8fbf2620c60.1 go: added buf.build/gen/go/connectrpc/eliza/connectrpc/go v1.11.0-20230727062025-d8fbf2620c60.1

Import paths

If you're consuming a publicly available generated SDK, an easy way to get the import paths for your packages is to load up the module on pkg.go.dev (for example, https://pkg.go.dev/buf.build/gen/go/connectrpc/eliza/connectrpc/go). From there, you can drill down into directories to get the import path for a particular package.

If you're not consuming a publicly available SDK, you can generally construct an import path by combining the elements that go into the import path: remote, module, plugin and proto package(s). Continuing with the connectrpc example:

  • remote: buf.build
  • module: connectrpc/eliza
  • plugin: connectrpc/go
  • proto package(s): The connectrpc/eliza module only has a single proto package, connectrpc.eliza.v1

From here, you can build up the package you'd expect,using the following syntax:

Go SDK import syntax
{bsrServer}/gen/go/{moduleOwner}/{moduleName}/{pluginOwner}/{pluginName}/{protoPackage}
Examplebuf.build/gen/go/connectrpc/eliza/connectrpc/go/connectrpc/eliza/v1
Legend:
constant{variable}

Certain plugins, like Connect and gRPC, generate code into subpackages (see Connect's reasoning). So, we tack on Connect's generated subpackage name and get this path, which contains our importable code:

buf.build/gen/go/connectrpc/eliza/connectrpc/go/connectrpc/eliza/v1/elizav1connect

Note the apparent duplication in the import path. In the example above, connectrpc/eliza is included in the path twice in separate locations, which may seem odd. However, this is a consequence of following good Protobuf package hygiene—a well-named package commonly shares some elements with the name of the module.

Versions

By default, when you go get a Buf module, the BSR generates code from the most recent reference for the module. However, you can also install a specific module version by referencing an explicit version or a branch name with the @ syntax. To discover SDK versions, you can browse a repository's SDKs page, which has installation instructions and an interactive UI.

Latest

To get the generated SDK for the latest version of the module:

$ go get buf.build/gen/go/connectrpc/eliza/connectrpc/go@latest

Commit

To get the generated SDK for the module at a commit:

$ go get buf.build/gen/go/connectrpc/eliza/connectrpc/go@d8fbf2620c604277a0ece1ff3a26f2ff

Tag

To get the generated SDK for the module at a tag:

$ go get buf.build/gen/go/connectrpc/eliza/connectrpc/go@foo

Branches

The BSR supports commits on branches. This feature enables you to push unreleased Protobuf file changes and consume generated code without affecting the main branch.

To get the generated SDK for the module on a branch:

$ go get buf.build/gen/go/connectrpc/eliza/connectrpc/go@dev
Caveats

References with names that contain / are not compatible with the Go generated SDKs versioning scheme.

Full syntax

Go module version syntax
{pluginVersion}-{moduleTimestamp}-{moduleCommit}.{pluginRevision}
Examplev1.11.0-20230727062025-d8fbf2620c60.1
Legend:
{variable}

With SDK versions (valid semver):

  • The version core is the plugin version 1.11.0
  • The semver pre-release version is composed of:
    • module commit timestamp (YYYYMMDDHHMMSS) 20230727062025
    • module commit short name (12 characters) d8fbf2620c60
  • The final identifier is the plugin revision 1 for the plugin version

Most users will likely use @latest, but if you need to reference a version explicitly, you can do so like this:

$ go get buf.build/gen/go/connectrpc/eliza/connectrpc/go@v1.11.0-20230727062025-d8fbf2620c60.1

For commits on branches, the commit timestamp component of the version is always zeroed out to easily differentiate package versions using commits on branches that aren't main.

Private generated SDKs

When using SDKs generated from private BSR repositories, you'll need to authenticate by including a personal API token for local use or a Bot user's API token for CI workflows.

The go tool authenticates with proxies using .netrc credentials or credentials directly specified in GOPROXY URLs. See the Authentication page for instructions on setting up your token and authenticating with .netrc.

You can also authenticate using direct credentials:

GOPROXY=https://$BSR_USER:$BSR_TOKEN@buf.build/gen/go

As mentioned in the Go docs on using direct credentials, use caution when taking this approach, as environment variables may appear in shell history and in logs.

Private modules are only accessible to authorized users and can't be pulled through the default module proxy at https://proxy.golang.org or have their checksums verified with the public checksum database at https://sum.golang.org/. To access private modules you need to specify a combination of GOPROXY, GOPRIVATE, GONOPROXY and/or GONOSUMDB.

There are two possible ways to configure Go for private modules:

  • Using GOPRIVATE=buf.build/gen/go. This implicitly sets GONOPROXY/GONOSUMDB to the same value, causing Go to use the direct strategy for fetching directly from BSR without going through the public proxy.

    Because GONOPROXY includes the Buf registry, this is not compatible with specifying auth directly in GOPROXY. Only netrc-based auth is supported in this configuration.

  • Using GOPROXY=https://buf.build/gen/go,$GOPROXY and GONOSUMDB=buf.build/gen/go. This instructs Go to try a module from Buf before falling back to the existing configured proxies. This works both for netrc and direct authentication.

Modify the Go environment using the export command in your shell or with the go env -w command to persist the change:

$ export GONOSUMDB=$GONOSUMDB,buf.build/gen/go
$ go env -w GONOSUMDB=$GONOSUMDB,buf.build/gen/go

For more information, see the official private modules documentation.

Available plugins

For a full list of supported plugins, navigate to the BSR plugins page and search for Go.

To learn more about how these plugins are packaged and distributed, go to the bufbuild/plugins repository. If you find a useful plugin that should be added, file an issue.