CtrlK
BlogDocsLog inGet started
Tessl Logo

testland/protobuf-versioning-strategy-reference

Pure-reference catalog of protobuf3 versioning and breaking-change rules: field-number reservation (reserve on delete; 1..536870911; 19000-19999 reserved), wire-safe vs wire-incompatible changes (add/remove safe with reservation; changing a field number always breaks), compatible type conversions (int32/uint32/int64/uint64/bool; sint32/sint64; string/bytes for UTF-8; enum/int), oneof + map constraints, and buf's four breaking categories (FILE/PACKAGE/WIRE_JSON/WIRE) with rule IDs. Use when designing a schema change or picking a buf breaking ruleset. This is the catalog of what is breaking and why, not a scanner; to detect changes in CI use buf-cli-lint-breaking-build, for the gRPC status-code vocabulary use grpc-status-code-mapping-reference, and for cross-service contract testing use protobuf-compat-checking.

76

Quality

95%

Does it follow best practices?

Run evals on this skill

Adds up to 20 points to the overall score

View guide

SecuritybySnyk

Passed

No findings from the security scan

Overview
Quality
Evals
Security
Files

buf-breaking-rules.mdreferences/

buf breaking-rule tables and worked evolution patterns

Full rule-ID tables for buf's four breaking categories, plus worked proto-evolution diffs. Sources: buf.build/docs/breaking/rules and protobuf.dev/programming-guides/proto3/.

FILE (default)

RuleDetects
ENUM_NO_DELETERemoved enum
MESSAGE_NO_DELETERemoved message
SERVICE_NO_DELETERemoved service
FILE_NO_DELETERemoved file
FIELD_SAME_NAMERenamed field
FIELD_SAME_TYPEType change
FIELD_SAME_CARDINALITYsingular <-> repeated

PACKAGE

RuleDetects
PACKAGE_NO_DELETERemoved package
PACKAGE_ENUM_NO_DELETEEnum deletion across files in package
PACKAGE_MESSAGE_NO_DELETEMessage deletion across files

WIRE_JSON

RuleDetects
ENUM_VALUE_NO_DELETE_UNLESS_NUMBER_RESERVEDDeleted enum value without reserve
FIELD_NO_DELETE_UNLESS_NUMBER_RESERVEDDeleted field without reserve
FIELD_SAME_JSON_NAMEJSON field name change

WIRE (most lenient)

RuleDetects
FIELD_WIRE_COMPATIBLE_TYPEType change incompatible at wire level (allows int32->int64 etc.)
FIELD_WIRE_COMPATIBLE_CARDINALITYCardinality change incompatible at wire

Worked evolution patterns

Adding an optional field

Safe (always):

message User {
   string name = 1;
+  string nickname = 2;
 }

Renaming a field

Add new, deprecate + reserve old:

message User {
   string name = 1;
-  string nickname = 2;
+  string display_name = 3;
+  reserved 2;
+  reserved "nickname";
 }

Consumers must migrate from nickname to display_name. The wire format reads either; the codegen forces consumers to update.

Promoting int32 to int64

Wire-compatible per protobuf3 docs:

message Counter {
-  int32 count = 1;
+  int64 count = 1;
 }

Old clients writing int32 still parse correctly. Old clients reading new int64 data truncate silently if the value exceeds int32 range.

Adding a field to a oneof

ALWAYS BREAKING. Don't.

message Event {
   oneof body {
     string text = 1;
     bytes binary = 2;
+    string emoji = 3;  // BREAKS old parsers
   }
 }

Mitigation: add the new variant as a non-oneof field; promote later in a separate proto file/package.

SKILL.md

tile.json