The compatibility-shaped gap¶
The registry stores, addresses and serves schemas. It does not check backward, forward or full compatibility, and it does not claim to.
Why not¶
Nothing in the estate has evolved a schema yet. Every service currently publishes to itself.
A compatibility model chosen now would be a guess about which kind of break will matter, and it would be an expensive guess: compatibility is schema-language-specific, so supporting two languages roughly doubles the work, and it is exactly the part where being wrong is worse than being absent. A check that answers confidently and wrongly is worse than no check, because people stop reading the schema.
Immutability and resolvability are worth having on their own, and they are the parts nothing else provides.
But the gap is shaped, not left open¶
Three commitments, all live today, so the check lands as an addition rather than a break.
1. The publish API already takes a compatibility mode¶
reg.Publish(ctx, s, schema.CompatibilityNone) // accepted
reg.Publish(ctx, s, schema.CompatibilityBackward) // ErrUnsupportedCompatibility
It is a required argument from the first release. Two consequences:
- Callers written today do not change signature when a checker arrives.
- A caller asking for a guarantee we cannot provide is told so, rather than quietly given none. That second one is the part that would otherwise rot: an optional argument that is ignored is a promise nobody knows is unkept.
2. A Checker interface exists per schema language¶
type Checker interface {
Language() Language
Check(ctx context.Context, prior, next Schema, mode Compatibility) error
}
NoCheck is registered for each language, and jsonschema.Checker and protobuf.Checker are the
no-ops a real implementation will replace.
They are not placeholders to be deleted. They make the mode argument and the checker lookup live code, so the path a real checker will take has been exercised before a real checker takes it. A seam nothing has ever travelled is a seam that will not fit when something does — and the test suite asserts, among other things, that the checker is handed the predecessor rather than the latest version, which is exactly the kind of thing a retrofit would otherwise discover was wrong.
3. The store keeps prior versions¶
Publishing retains every earlier version under the same name, so a checker will have a predecessor to compare against.
This is the one that would be silently lost. A store that kept only the latest version would look
identical from every other angle, and the loss would surface on the day somebody tried to add the
check — by which point the backfill needs data nobody has. So it is a documented requirement of the
Store interface, and it has its own test.
What a version bump means today¶
Only that the bytes differ.
It is not a compatibility claim, and nothing should read it as one. That is also why versions are integers rather than semantic versions: a semantic version would imply a promise nothing verifies, which is precisely the class of claim this estate has spent time removing.
And the one idea taken from Confluent¶
Compatibility as an operation a caller asks for explicitly, rather than an implicit property of publishing. Everything else about their API was rejected, but that part is right, and it is what the mode argument is.