Coding Bits
April 17th, 2024 Protocols

Changing gRPC Schemas

What changes can you make to a gRPC schema that's already in use?

Honestly, I always forget these rules, or get paranoid when I'm touching messages that are already deployed, so it was time to find out what these rules are. I came across this Medium post by Toan Hoang which listed them, and I thought I'd make a note of them here.

Here they are in brief.

Non-Breaking Changes

The following changes are completely safe, and will not break existing clients or servers using an earlier version of the schema:

  • Adding a new service
  • Adding a new method to an existing service
  • Adding a new field to an existing message
  • Adding a value to an enum

How peers handle unrecognised fields is as follows:

  • If the peer implements a version of the schema with the new field defined, but the message does not have that field set, the field will be set to the default value. 
  • If the peer receives a message with a field not recognised by the schema, the field will be added to the message's unknown fields.

The following changes are possible, but may cause issues if clients or servers are not updated with the new schema soon after they're made:

  • Removing a field — this is treated as an unrecognised field using the rules listed above. The important thing to avoid is reusing the field number, which can result in a breaking change if clients are not updated to the newer schema. There is some way to reserve names and numbers to avoid this, but I've never used this myself.
  • Renaming a message — message names aren't typically sent across the wire, so this won't be a huge issue unless you're using the Any message type.
  • Nesting or un-nesting messages — this is effectively the same as renaming them.

Breaking Changes

These are the changes that likely to cause issues, and will most likely require a delicate roll-out to avoid errors.

  • Renaming a field — not so much an issue when using protobuf as a transfer protocol, since numbers are used to identify the field. But can still be an issue if using JSON.
  • Changing the fields's data type — there is a set of rules governing convertable data types so this is not a hard-and-fast issue.
  • Changing a field's number — this is the big one.
  • Removing or renaming a package, service, or method — an `UNIMPLEMENTED` error will be raised if an unrecognised package, service, or method request is received by a peer.

Another useful resource is this Earthly blog post by John Gramila about good design practices when considering forward and backwards compatability.

Happy gRPCing.