Back to results for “gRPC Services”
.NET › gRPC Services

How would you version a gRPC service's contract while maintaining backward compatibility with existing clients?

Intermediate

Answer

Protobuf inherently supports additive, backward-compatible evolution: adding new fields (with new numbers) to existing messages doesn't break old clients (which simply ignore unknown fields) or old servers (which see new fields as absent/default on requests from newer clients) -- for genuinely breaking changes (removing or fundamentally changing a field's meaning), the convention is defining an entirely new service or method (like GetOrderV2) or a new package/namespace, similar in spirit to REST's URL-based versioning but expressed through the protobuf package/service naming instead.
// Adding a field is safe -- old clients simply don't send/see it
message OrderRequest {
  int32 order_id = 1;
  string include_details = 2;  // NEW field, old clients omit it, defaults apply
}

// Breaking change: new service version entirely
service OrderServiceV2 {
  rpc GetOrder (GetOrderRequestV2) returns (OrderResponseV2);
}
Real-world example An internal platform evolves its OrderService contract by only ever adding new optional fields for two years, avoiding the need for a breaking V2 service entirely, since protobuf's additive-evolution model accommodated every required change without compatibility issues.

Common follow-ups: How does protobuf handle a field present in a newer message but absent in the client's older generated code?;When is a new service version truly unavoidable versus additive evolution being sufficient?