gRPC service upgrade, versioning

7,406 views
Skip to first unread message

Scott Devoid

unread,
Jun 20, 2016, 2:58:48 PM6/20/16
to grp...@googlegroups.com
Hi all,

What are the 'best practices' for handling service changes and API
versioning in gRPC? At the protobuf level, I know the answer is:
append fields and never reuse a field number. Or at the very least,
comment out the field and wait until you can be sure that no component
uses the old field.

But there are two scenarios that I can think of:

- Adding RPC methods or altering RPC method signatures. I assume both
the client and the server need to agree here? Do people implement a
"GetVersion()" method? or something else?

- When the client wants to send fields in a request that are
semantically required but the server's version of the protobuf doesn't
include those fields. Is there a way for the server to indicate that
it received fields that it could not parse?

Thank you!
~ Scott

Carl Mastrangelo

unread,
Jun 22, 2016, 12:33:02 PM6/22/16
to grpc.io
You should assume that any code you distribute will be around forever and people will not update it.  With this in mind, you should plan for backwards compatibility forever and design your APIs appropriately.  If you have special knowledge that you can update all clients/ servers (via some sort of auto updating package manager), then you need to at least support all methods until you know for sure all have updated.  You can include a user agent string in the headers of your API calls to indicate what version is running.  

In general:
- As you said never reuse a field number
- Never change the type of a field.  Even if you know what you are doing, don't.
- If you are on proto2, never use required fields.  They are more dangerous than you think.  They do not stand the test of time
- Don't use or depend on default values.

There are a couple ways of supporting older clients.  One way is the union style:

message DoSomethingRequest {
  DoItWayOne first = 1;
  DoItWayTwo second = 2;
}


When you want to add a third way, just add it in.  Servers need to check which way is set and use the appropriate code path.  Also all servers will need to be updated before releasing it in the clients.

Always make sure that each client can work with the current server version and the next server version.  Serves must work with the current client and the next client.  This forms a chain of compatibility that makes rolling out new versions easy and makes rolling back safe!

Hopefully this helps.

Scott Devoid

unread,
Jun 24, 2016, 11:46:20 AM6/24/16
to Carl Mastrangelo, grpc.io
Thank you for the reply.

> ... Also all servers will
> need to be updated before releasing it in the clients.
>
> Always make sure that each client can work with the current server version
> and the next server version. Serves must work with the current client and
> the next client. This forms a chain of compatibility that makes rolling out
> new versions easy and makes rolling back safe!

But in the roll-back scenario if you only have control over the server
you could still get into the situation where the client has a newer
version than the server, right? So it's still necessary for some form
of negotiation. The client needs to figure out that "DoItWayThree"
won't work and fall back to "DoItWayTwo".

Right now, at least with the Go libraries, the only way to implement
all of this is a lot of boilerplate. I'm hoping there's a better way.

Thanks,
~ Scott

Carl Mastrangelo

unread,
Jun 24, 2016, 12:08:08 PM6/24/16
to grpc.io, not...@google.com
The assumption is that you roll out clients and servers at different times, and then once you feel they are stable, roll out the counter part.  In effect, you can only roll back one or the other at a given time, but no negotiation is needed.  Also, in general its better to be indefinitely backwards compatible, because there still tend to be clients, or servers, that will never upgrade.  It's more work in the mean time, but it pays dividends over time.  Users *really* like backwards compatibility.  It's just us developers that feel the pain for it.

tar...@gmail.com

unread,
May 7, 2018, 10:45:32 AM5/7/18
to grpc.io


On Wednesday, June 22, 2016 at 11:33:02 AM UTC-5, Carl Mastrangelo wrote:
You should assume that any code you distribute will be around forever and people will not update it.  With this in mind, you should plan for backwards compatibility forever and design your APIs appropriately.  If you have special knowledge that you can update all clients/ servers


e.g. We have a scenario where our gPRC interface is internal to our large organization, so we can work with other teams to get them updated and know for sure no 'v1' requests will then come in, and delete it.
Reply all
Reply to author
Forward
0 new messages