Schema evolution review

Protocol Buffers Schema Breaking-Change Diff

Compare a baseline and candidate schema before publishing an API change. Review tag identity, fields, enums and RPCs with separate binary-wire, ProtoJSON and generated API impacts.

Baseline and candidate schemas

Baseline (old)

No files selected.

Candidate (new)

No files selected.

Chosen files and pasted text are combined. A single paste is named schema.proto; use // file: api/order.proto on a separate line for each virtual file. Import paths must match supplied names relative to the import root. Plain multi-file selection uses file basenames; use paste markers for nested paths. Clear stale files before loading a replacement set.

Each side: up to 32 UTF-8 files, 4 MiB of text, 250,000 tokens, 10,000 definitions, 40,000 fields/enum values and 64 nested levels. Comparison stops after 30 seconds; limits abort rather than truncate. Supports proto2/proto3, excluding Editions, groups and extensions.

Paste or choose baseline and candidate schemas.

Schema text, filenames, qualified symbols and reports stay in this browser. No imports, repositories, or code generators are loaded from your input.

Binary wire compatibility differs from JSON and code compatibility

Protocol Buffers encode fields using numeric tags and wire types. Renaming a field can preserve its binary identity while changing generated accessors and ProtoJSON keys. Changing its number can leave its JSON key intact while losing the binary identity. This tool reports the dimensions separately instead of treating every textual change alike.

Type changes require more than comparing wire-type numbers. Zigzag integers, ordinary varints, floating-point bits and fixed-width integers can have different meanings. Wider integers, string/bytes interchange, embedded messages and map-entry conversions can also require restrictions on real payloads and rollout order.

Reserved numbers, oneofs, enum values and RPC signatures

Reserve deleted field numbers and names to protect historical binary and JSON/TextFormat identities. A different name on the same tag is a reuse candidate; inspect whether it is a deliberate rename or entirely new meaning. This comparison only knows the two supplied revisions.

Moving independent fields into a shared oneof can clear values that previously coexisted. Proto2 closed enums and proto3 open enums handle unknown values differently; enum names also travel in JSON. Changes to RPC request/response types or streaming modes affect clients and server implementations even when the underlying messages still parse.

Verify with your actual toolchain

This tool uses protobufjs 8.8.0 for local parsing and a bounded proto2/proto3 comparison model. It does not run protoc or reproduce every Buf rule. Missing imports, invalid checked declarations and unresolved references make the result incomplete; custom options are compared but their behavior is not interpreted. Editions, groups and extensions stop comparison.

Use your target compiler, code-generator versions, configured buf breaking checks, generated clients and representative payload round trips. Test old writers with new readers and new writers with old readers. Existing persisted data, Any type URLs, HTTP/custom bindings and application-level meaning require separate review.

Frequently asked questions

Why compare fields by number instead of name?

The binary wire format identifies a field by its number. A rename can preserve binary identity while breaking generated accessors and JSON keys. A renumber changes the binary identity even if the name stays the same.

Is int32 to int64 a safe change?

It is conditionally binary compatible. Values outside the old 32-bit range can be truncated by old readers. ProtoJSON representation and generated types also change. Keep old range restrictions until every reader is updated.

How do I supply imports?

Choose multiple .proto files with matching import-root-relative names, or paste a bundle separated by // file: path/to/file.proto lines. Files and imports are virtual and local; missing imports are never fetched and make the result incomplete. Public import visibility is modeled.

Does this replace protoc or buf breaking?

No. This is a bounded structural analysis aid for proto2/proto3 messages, enums, services, maps and oneofs. Editions, groups and extensions are refused. Use the actual compiler, configured Buf rules, generated clients and representative payload tests for approval.

Are schemas uploaded or sent to analytics?

No. Schemas are parsed in a local cancellable worker. Filenames, schema text, derived tables and reports are explicitly masked for Clarity and remain in the browser.

Primary format references

See the official proto3 schema-evolution guide, proto2 guide, ProtoJSON wire-safety rules and Buf breaking-change rules.