| name | schema-registry-evolution |
| description | Playbook for managing Avro/Protobuf/JSON Schema schemas in a registry — choosing a compatibility mode, executing safe schema changes, and handling breaking changes without consumer downtime. |
Schema Registry Evolution
When to Use This Skill
Any time a schema change is proposed on a Kafka topic, or when a team is choosing a compatibility mode for a new subject in Confluent Schema Registry or AWS Glue Schema Registry.
Compatibility Mode Selection
| Mode | What it allows | Use when |
|---|
BACKWARD | New schema reads data written with old schema | Consumers upgrade first; producer adds optional fields |
FORWARD | Old schema reads data written with new schema | Producers upgrade first; adds fields consumers ignore |
FULL | Both backward + forward | You need rolling deploys with mixed versions in flight |
NONE | No compatibility check | Internal dev topics only — never production |
Default recommendation: FULL for any topic consumed by multiple independent teams. BACKWARD for tightly-coupled producer/consumer pairs where you always update consumers first.
Safe Change Checklist
Adding a field (safe):
- Add with a default value in the schema (
"default": null for Avro unions; optional in Protobuf).
- Register the new schema version in the registry; confirm compatibility check passes.
- Deploy the producer that starts writing the new field.
- Deploy consumers that read the new field.
- After all consumers are deployed, remove the default if the field is now required.
Removing a field (requires care):
- First mark it as deprecated in documentation; don't remove yet.
- Deploy all consumers to stop reading the field.
- Once no consumer reads it, register the schema without the field (only safe under
BACKWARD or FULL).
- Never remove a field in the same release that adds another field — one change per version.
Renaming a field (breaking under all modes):
- Avro/JSON Schema have no rename primitive. Treat as add + deprecate: add the new name (with default), migrate consumers, then remove the old name across two separate schema versions.
Breaking Change Protocol
When a breaking change is unavoidable (type change, semantic reinterpretation):
- Create a new subject (new topic name or
<topic>-v2 convention).
- Run the old and new topics in parallel; dual-publish from the producer if needed.
- Migrate consumers to the new topic.
- Retire the old topic after a migration window.
Never mutate the meaning of an existing field name — consumers can't distinguish a type change from a bug.
Registry Operations Quick Reference
curl -X POST -H "Content-Type: application/vnd.schemaregistry.v1+json" \
--data '{"schema": "<escaped-schema>"}' \
http://registry:8081/compatibility/subjects/<topic>-value/versions/latest
curl http://registry:8081/subjects/<topic>-value/versions
curl http://registry:8081/subjects/<topic>-value/versions/3
Pitfalls
- Registering a schema without checking compatibility first — the producer deploys, breaks consumers, and you discover it in prod.
- Using
NONE mode on a shared topic because "it's easier" — any producer deploy can silently corrupt consumer deserialization.
- Storing the schema ID in a sidecar database instead of trusting the registry wire format — the magic byte + schema ID header in every Kafka message is the contract; don't duplicate it.
- Forgetting that
null is a type in Avro — a nullable field must be a union ["null", "string"], not just "string" with a null default.
See also