2

I want to preserve my application from future issues with backward compatibility. Now I have this version of test.proto:

syntax = "proto3";

service TestApi {
    rpc DeleteFoo(DeleteFooIn) returns (BoolResult) {}
    rpc DeleteBar(DeleteBarIn) returns (BoolResult) {}
}

message DeleteFooIn {
    int32 id = 1;
}

message DeleteBarIn {
    int32 id = 1;
}

message BoolResult {
    bool result = 1;
}

I'm interested in a case when I will want to change result message of DeleteBar() to a message like "DeleteBarOut":

syntax = "proto3";

service TestApi {
    rpc DeleteFoo(DeleteFooIn) returns (BoolResult) {}
    rpc DeleteBar(DeleteBarIn) returns (DeleteBarOut) {}
}

message DeleteFooIn {
    int32 id = 1;
}

message DeleteBarIn {
    int32 id = 1;
}

message DeleteBarOut {
    reserved 1;
    string time = 2;
}

message BoolResult {
    bool result = 1;
}

The question is about backward compatibility on-wire with the old .proto. Can I change the name of the result message from "BoolResult" to "DeleteBarOut"?

Or I should save the old name of the message and edit fields list of "BoolResult"? But then how can I save DeleteFoo() from any changes in this solution?

1 Answers1

0

When making a breaking change to an API like this, it is a common practice to support both versions while transitioning. In order to do this, you would need to add a version field to the request message and then in your request handler, route the message to different backends based on which version is specified. Once there is no more traffic going to the v1 backend you can make a hard cutover to v2 and stop supporting v1.

Unfortunately, if you just change the RPC definition without versioning, it is impossible to avoid a version incompatibility between the server and the client. The other option of course is to add a new RPC endpoint rather than modifying an existing one.

In general if you are making breaking API changes you're going to have an unpleasant time.

Nick Chapman
  • 4,402
  • 1
  • 27
  • 41