Kafka Avro Schema Diff
Two Avro schemas compared as schemas rather than as text, with the direction each change breaks worked out from Avro's resolution rules.
Nothing is uploaded: the comparison runs in this tab.
Changes
Common mistakes
These are the ones that fail silently. The config is accepted, nothing raises an error, and the consequence arrives later.
Assuming a compatible change is compatible in both directions
Adding a field with a default is backward compatible and not forward compatible. Which one you need depends on whether readers or writers upgrade first.
Instead:Decide the deployment order first, then pick the compatibility mode that matches it.
Renaming a field
Avro matches by name, so a rename is a delete plus an add. Readers on the old schema lose the value entirely.
Instead:Add an alias instead, which schema resolution understands.
Changing a field's type to a union
Promoting string to [null, string] is not compatible in either direction unless defaults line up exactly, because the encoding changes.
Instead:Add a new field and deprecate the old one.
Every change, and the direction it breaks
A text diff of two schemas tells you which lines moved. This one pairs fields by name and states, from Avro's resolution rules, which direction each change stops working in.
Field order is free and looks dangerous
Avro writes a record's fields in schema order and resolves them by name, so a reader with a different order still finds each value. The encoded bytes change completely and the meaning does not. This is the one structural change that looks alarming in a diff and costs nothing, which is why it is called out rather than left in a list of changes that mostly do matter.
A union branch added breaks forward, and removed breaks backward
Adding a branch is safe for a consumer on the new schema and fatal for one still on the old, because that consumer has no branch for the value it just received. Removing one is the mirror image: data already written can carry the removed branch and a new reader has nowhere to put it. The field still exists and still has a plausible type in both cases, which is what makes this easy to miss in review.
A namespace move breaks nothing the registry checks
Avro compares the short name of a type, then the reader's aliases. So moving a record between namespaces resolves, the registry accepts it, and this page reports no incompatibility either, because that would be disagreeing with the thing it predicts. It is still a breaking change everywhere else: generated classes move package, the fingerprint changes, and any consumer pinning the fullname stops matching. That is why it appears as a change with its own severity.
Documentation and logical types are outside the fingerprint
The parsing canonical form keeps type, name, fields, symbols, items, values and size, and strips everything else. So a change to a doc string, an alias, a default or a logical type leaves the fingerprint identical while changing what generated code does. When the panel reports the same fingerprint on both sides and a list of changes above it, that is the reason.
This says what changed, not whether it is allowed
Whether a breaking change matters depends on the compatibility level set on the subject, and on which of your consumers have actually been redeployed. The compatibility checker on this site gives the registry's own verdict for a chosen level, including the transitive ones. Use this page to review a change and that one to predict the registry.