Schema Compatibility Checker
Compare two schema versions before you deploy. Avro gets a definite backward/forward verdict from the specified rules; Protobuf gets three separate answers, because “compatible” means three different things there.
Avro's resolution rules are specified, so this gives a definite answer: backward means a reader on the new schema can read old data, forward means a reader on the old schema can read new data, and full means both. Protobuf has three different notions of "compatible" and a change can be safe under one while breaking another — renaming a field is invisible on the wire and fatal for protobuf JSON. All three are reported separately rather than blended into one verdict.
{{ error }}
They differ only in documentation, aliases, defaults or formatting — the canonical
forms are identical, so nothing about reading data changes.These are the same schema
{{ v.label }}
{{ v.ok ? v.okText : v.badText }}
{{ grp.label }}{{ grp.issues.length }}
- {{ d.path }} — {{ d.message }}
No differences that affect compatibility.
A protobuf payload is decodable without its schema — every field carries its
number and wire type. What it does not carry is names or declared types, so the same bytes
genuinely have several valid readings. Every plausible one is shown rather than one
confident guess. Paste a .proto below to resolve the names.
Add a .proto to resolve field names (optional)
{{ error }}
{{ framing.note }}
- {{ w }}
Field number{{ schemaNotes.unknown.length === 1 ? '' : 's' }} {{ schemaNotes.unknown.join(', ') }} appear in the payload but not in the schema — that is what version skew looks like on the wire.
Not present in this payload: {{ schemaNotes.missing.join(', ') }}. In proto3 an unset field and a zero value are indistinguishable, so absence here does not prove it was never set.
-
{{ f.number }}
{{ f.name }}
{{ f.wireName }}
declared {{ f.declaredType }}
- {{ r.as }}{{ r.value }}
Nothing decoded from those bytes.
Deterministic on purpose — the same schema always produces the same sample, so it can go straight into a fixture or a test without changing under you. Output follows protobuf's canonical JSON mapping, which is where the surprises live: lowerCamelCase keys, 64-bit integers as strings, enums as symbol names, and Timestamp as a string rather than an object.
{{ sampleText || 'Generated JSON appears here…' }}
{{ error }}
Everything is parsed and analysed entirely in your browser. Nothing you paste is ever uploaded to a server.
Two formats, two very different kinds of answer
Avro's specification defines schema resolution precisely: for any writer schema and any reader schema it states whether the data can be read and how. That means a definite verdict is possible, and this tool gives one. Protobuf has no equivalent document — its compatibility rules are convention built on how the wire format happens to work — so it gets an honest report instead of a false certainty.
Protobuf: three answers, not one
Renaming a field is completely invisible on the wire, because binary encoding uses the field number and never the name. The same rename instantly breaks protobuf JSON, which keys off the name. And it breaks generated code. Those are three different verdicts for one change, and collapsing them into a single "compatible / not compatible" is how tools mislead people into shipping a data-corrupting release or blocking a harmless one.
If you only look at one, look at wire format. A source break is loud — the build fails and you fix it. A wire break can quietly misinterpret data that is already stored.
The removal that looks safe and is not
Deleting a field is fine for the wire format today. The risk is tomorrow: the number is still present in existing data, so if a later version reuses it for a different type, old and new messages silently misread each other. Reserving the number makes that impossible, which is why an unreserved removal is reported as a warning here rather than a pass.
Avro: which direction matters depends on your deploy order
Backward compatibility is what you need to deploy readers first; forward is what you need to deploy writers first. Only when both hold does the order stop mattering. Adding a field with a default is backward compatible; adding one without a default is not, because there is nothing to fill it with when reading older data.
Exploring a single schema instead of comparing two?
Use the Avro Schema Viewer or the Protobuf Schema Viewer.
Frequently asked questions
What is the difference between backward and forward compatibility?
Backward means a reader using the NEW schema can read data that was written with the OLD one — that is what you need when you deploy readers before writers. Forward means a reader still on the OLD schema can read data written with the NEW one, which is what you need when writers go first. Full means both, and only then does deployment order stop mattering.
Why does Protobuf get three verdicts instead of one?
Because “compatible” genuinely means three different things there, and a change can be safe under one while breaking another. Renaming a field is completely invisible on the wire — binary encoding uses the field number — but protobuf JSON keys off the name, so JSON consumers break instantly. Blending those into one answer is how tools mislead people, so they are reported separately.
Which of the three Protobuf verdicts should I care about most?
Wire format, because it is the one that corrupts data rather than merely failing to compile. A source-compatibility break is loud: your build fails and you fix it. A wire break can silently misinterpret production data that is already stored or in flight.
Why does removing a field warn even when the wire format is reported as fine?
Because the field number is still out there in existing data. If a later version reuses that number for a different type, old and new messages will silently misread each other. Adding a reserved declaration for the number makes that impossible, which is why the tool checks for it and treats an unreserved removal as a warning rather than a pass.
How can Avro give a definite answer when Protobuf cannot?
Avro's specification defines schema resolution precisely: for any writer and reader schema it states whether the data can be read, and how. Protobuf has no equivalent document — its compatibility rules are convention built on how the wire format happens to work. So Avro gets a verdict and Protobuf gets an honest report.
Is my schema uploaded anywhere?
No. Both schemas are parsed and compared entirely in your browser. Nothing is sent to a server, which matters because a schema describes your internal data model.