Evolving the Wire Format
You'll learn to
- -Apply protobuf's backward/forward compatibility rules when adding, removing, or changing fields
- -Use `oneof` correctly for a field that can hold exactly one of several possible types
Protobuf was specifically designed with schema evolution in mind - old clients and new servers, or new clients and old servers, need to keep working together during a rolling deployment, the exact same problem the REST versioning chapter covered, just with protobuf's own specific compatibility rules.
What's Safe to Change
- -Safe: adding a new field with a new, never-used field number. Old code simply ignores fields it doesn't recognize.
- -Safe: removing a field, as long as its number is marked `reserved` so it's never accidentally reused.
- -Unsafe: changing a field's number. The wire format identifies fields by number, not name - changing it is indistinguishable from removing the old field and adding an unrelated new one.
- -Unsafe: changing a field's type to an incompatible one (e.g. `string` to `int32`). Some type changes within the same "wire type" family are safe (`int32` to `int64`); most are not.
- -Generally safe: renaming a field. Since the wire format only carries the number, a rename doesn't affect already-compiled binaries - but it does affect any human-readable serialization (like protobuf's JSON mapping) or generated code relying on the field's name.
oneof: Exactly One of Several Types
message PaymentMethod {
oneof method {
CreditCard credit_card = 1;
BankTransfer bank_transfer = 2;
DigitalWallet digital_wallet = 3;
}
}`oneof` declares that exactly one of the listed fields is set at a time - setting `credit_card` automatically clears `bank_transfer` or `digital_wallet` if either was previously set, and generated code exposes a way to check which one is currently set. This is protobuf's answer to a union type: without `oneof`, a message with three optional fields representing mutually exclusive alternatives leaves it ambiguous (and possible, incorrectly) for more than one to be set simultaneously.
Adding a New oneof Option
message PaymentMethod {
oneof method {
CreditCard credit_card = 1;
BankTransfer bank_transfer = 2;
DigitalWallet digital_wallet = 3;
Cryptocurrency cryptocurrency = 4; // new option, safe to add
}
}Adding a new option to an existing `oneof` is additive and safe, following the same "new field, new number" rule as any other field - old clients that don't know about `cryptocurrency` simply can't construct or recognize a message using that option, but they aren't broken by its existence, they just don't support it yet.
A common mistake: reordering fields in the .proto file, assuming it's purely cosmetic. It genuinely is cosmetic for the wire format (which only cares about field numbers), but reordering can still confuse a human reader comparing an old and new version of the schema - keep the numeric field numbers as the actual source of truth, not the field's position in the file.
Interview Signal is part of Pro
See a real weak answer next to a real strong one for this exact topic.
Quiz is part of Pro
Test what you just read with a short quiz, and bank the XP.
Design Wire Evolution in the API Design Lab's gRPC & Event-Driven act.