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

What is protobuf field numbering, and why must you never reuse or renumber a field once a message definition has shipped to production?

Intermediate

Answer

Each field in a protobuf message has a unique number (like `string name = 1;`) that's actually what's encoded on the wire, not the field name itself -- protobuf's binary encoding uses these numbers for identification, so reusing a previously-used number for a different field, or renumbering an existing field, can cause old serialized data (or a client running an older version of the contract) to be misinterpreted as the wrong field entirely, silently corrupting data rather than failing loudly with a clear error.
// Original message (version 1)
message Order { int32 id = 1; string status = 2; }

// SAFE evolution: add new fields with NEW numbers, never reuse 1 or 2
message Order { int32 id = 1; string status = 2; string customer_email = 3; }

// DANGEROUS: never do this -- reusing field number 2 for a different purpose
// message Order { int32 id = 1; int32 status_code = 2; }  // BREAKS compatibility silently
Real-world example A subtle production data corruption bug traced back to a well-meaning developer who renamed and renumbered a deprecated protobuf field for 'cleanliness', unaware this broke binary compatibility with clients still running the previous contract version.

Common follow-ups: How does protobuf's `reserved` keyword help prevent accidental field number reuse?;What's the protobuf convention for marking a field as deprecated without removing it?