Articles
Kafka Schema Registry Interview Questions: Compatibility and Safe Schema Changes
Practice Kafka Schema Registry interviews with Avro reader/writer examples, defaults, transitive compatibility, and rollout decisions that preserve replay.
Kafka Schema Registry interview questions become much clearer when you name two things before answering: the schema that wrote the event and the schema that will read it. “We made a backward-compatible change” is incomplete until you can explain which consumers can read which retained events.
This guide uses ten original binary-read and write checks executed with Apache Avro 1.12.0. The examples expose missing defaults, directional numeric promotion, and a three-version replay failure. We did not deploy Kafka or a Schema Registry service; registry-policy conclusions below come from Confluent documentation, while the decoded values and errors come from local execution.
Start by drawing the read relationships, then discuss rollout and recovery.
Which Schema Writes, and Which Schema Reads?
Backward compatibility asks whether a new reader can consume data from the preceding writer schema. Forward compatibility asks whether an older reader can consume data from the new writer schema. Full compatibility combines both directions. Transitive variants extend the relevant comparison across the registered history rather than only the latest version. Confluent schema evolution
For a concrete answer, describe the arrow: old writer to new reader, or new writer to old reader. The word “backward” alone is easy to reverse under pressure. The arrow also makes your test plan reviewable: someone else can see which bytes you generated and which reader you applied.
Avro distinguishes the writer's schema from the reader's expected schema during resolution. This article stays within Avro; Protobuf and JSON Schema have different compatibility rules. Do not transfer a successful Avro example to another format simply because the same registry supports both. Apache Avro specification
Our records all use the name Event. Keeping the record identity stable avoids introducing a separate naming change into a field-evolution exercise. In a real incident, record names and namespaces belong in the diagnostic evidence too.
Add a Field and Predict the Decoded Record
The original writer schema has one integer field:
{
"type": "record",
"name": "Event",
"fields": [{"name": "id", "type": "int"}]
}
The new schema adds a string field with a default:
{
"type": "record",
"name": "Event",
"fields": [
{"name": "id", "type": "int"},
{"name": "region", "type": "string", "default": "unknown"}
]
}
We wrote {"id": 7} with the old schema and read those bytes with the new schema. The result was {"id": 7, "region": "unknown"}. The reader filled information absent from the writer's schema.
We then wrote {"id": 7, "region": "EU"} with the new schema and used the old reader. It returned {"id": 7}. The extra writer field did not become part of the old reader's result.
Those are two separate observations, not one vague assertion that “adding a field is safe.” If the new application refuses to process the value unknown, binary resolution can succeed while the application still fails. The test needs both a decoding expectation and a business-behavior expectation.
Nullable Does Not Mean a Reader Default Exists
Next, remove the default from the new region field. Reading old bytes now raises SchemaResolutionException. Changing its type to ["null", "string"] without adding a default still raises the same error for this old-writer/new-reader pair.
A nullable type permits a null value when that field is represented. A reader default supplies a value when the writer schema lacks the field. These solve different problems. Avro's specification describes defaults as part of resolution for missing reader fields. Avro defaults and resolution
We also tried writing {"id": 7} directly with the new schema whose nonnullable region had default unknown. The Apache Python writer raised AvroTypeException. In this tested implementation, the declared default did not turn the omitted string field into a valid writer input.
Do not generalize that one writer result into a claim about every serializer's convenience behavior. Libraries can prepare records differently before encoding. State which implementation you used and inspect whether an application filled a value before it reached Avro.
The useful interview follow-up is: what does the fallback mean? A region of unknown might be acceptable for analytics enrichment and unacceptable for a routing decision. Pick a default that preserves an honest meaning, rather than selecting one only because it makes a compatibility test pass.
Read the Directional Test Matrix
The local fixture produced the following results. “Old” is the one-field schema above; the added-field variants keep the same record name.
| Writer → reader | Result |
|---|---|
| Old → added region with default | Pass; region becomes unknown |
| Added region → old | Pass; region omitted from result |
| Old → required region | Resolution error |
| Old → nullable region, no default | Resolution error |
| Integer id → long id | Pass; id is 7 |
| Long id → integer id | Resolution error |
The numeric pair is especially useful because the written value is only 7. A human can see that it fits in an integer, yet the long-writer/integer-reader combination fails schema resolution. Compatibility is not established by choosing a small example value that happens to fit the narrower range.
Our test uses Avro's binary encoder and DatumReader with both schemas supplied. It does not include a Confluent wire envelope, schema lookup, authentication, or a consumer framework. Those layers can fail independently and need their own diagnostic checks.
When presenting a reproduction, preserve the writer schema alongside the bytes. Passing an arbitrary newer schema as if it were the writer schema can change the question you are testing. A successful decode obtained from the wrong setup is not evidence that the intended migration works.
Why Two Adjacent Successes Do Not Prove Replay Safety
Consider an original three-version sequence. All versions retain integer id:
- Version 1 also has integer
value. - Version 2 removes
value. - Version 3 adds string
valuewith defaultunknown.
The local reader for version 2 reads version 1 data successfully and ignores value. The reader for version 3 reads version 2 data successfully and supplies unknown. But the version 3 reader fails when given version 1 bytes containing integer value.
The default does not override an incompatible field that actually exists in the writer schema. It covers absence, not an arbitrary type mismatch. That explains why the two neighboring transitions can succeed while the long-distance read fails.
Confluent documents non-transitive BACKWARD checks against the latest schema and BACKWARD_TRANSITIVE checks against prior registered schemas. The default is non-transitive BACKWARD; inspect actual configuration rather than assuming the default applies to your subject. Compatibility scope
Applied to our sequence, checking only the latest pair would miss the demonstrated version 1 to version 3 problem. A transitive backward check should reject that incompatible historical relationship. This is a documentation-based policy prediction, not a response observed from a running Registry API.
The retained-data question is practical: will an outage recovery, new consumer group, or backfill encounter version 1 events? If yes, replay belongs in the release test even when current traffic uses version 2 exclusively.
Turn the Matrix Into a Rollout Plan
For a backward-only guarantee, Confluent recommends updating consumers before new producers, because older readers are not assured of understanding the new writer schema. Full compatibility allows independent upgrades for the checked schema relationships. Client upgrade order
A useful preparation answer then adds the application-specific steps. Inventory consumers, determine which historical versions remain reachable, and test the candidate reader against representative retained events. Include defaults and boundary values, not only a freshly generated happy-path record.
Before changing producers, verify that the required consumers have adopted the intended reader behavior. A deployment completion signal should identify the running version, not merely show that a build was uploaded. Otherwise, an old worker can remain in service during the transition.
For the three-version fixture, a safer design might keep the original integer field and introduce a differently named string field with clearly defined meaning. That is an editorial migration option, not a universally correct replacement. You still need to decide which field is authoritative, how long dual writing lasts, and whether consumers can process missing historical values.
Avoid recommending deletion of historical data simply to make a compatibility story easier. Data retention, replay obligations, and downstream dependencies are part of the problem statement. If a deliberate breaking migration is necessary, describe the new contract and transition boundary explicitly.
What Should You Check in the Registry?
Treat registration, compatibility checking, and consumption as distinct operations. Confluent's API exposes subject/version resources and compatibility operations. A release process should record the subject, candidate schema, effective compatibility setting, and versions being compared. Schema Registry API reference
The subject matters because it defines the schema history against which the policy operates. Seeing a schema somewhere in the registry does not establish that it was checked against the history your consumer actually uses. Resolve the application's naming configuration before diagnosing an unexpected acceptance or rejection.
For an unexpected result, first reproduce the exact schema pair and policy scope. Then inspect whether the caller performed a compatibility test, registered a version, or simply looked up an existing schema. Those operations produce different evidence.
Finally, distinguish structural acceptance from semantic validation. A field can retain its numeric type while changing from milliseconds to seconds. A schema check may accept the structure, while timeout behavior becomes wrong by a factor of one thousand. Include a semantic fixture with expected application output in the release evidence.
Explain Rollback Without Forgetting New Events
Rolling a producer back does not erase events already written with its newer schema. A consumer rollback must therefore consider both retained old events and the new events created during the failed release.
In the added-region example, the old reader can decode the tested new records, but it discards region. Whether that is an acceptable rollback depends on the application. A downstream action that now requires region may still be incompatible even though the Avro read succeeds.
A concise rollback plan identifies the writer versions already present, the readers that will run afterward, and the expected handling of each pair. Preserve the schema and artifact evidence needed to reproduce failures. Do not treat changing a compatibility setting as rewriting previously published bytes.
For an interview, finish with the unresolved question that would change your recommendation: how far back must this consumer replay, and what business meaning is required from every decoded record? That connects a technical mode choice to an operational requirement.
Practice the Contract and Recovery Discussion
| Question | Practice focus |
|---|---|
| Explain ETL schema changes and ensure integrity | Separate structural and semantic changes |
| Design Real-Time Analytics Pipeline with Kafka and Flink | Place compatibility in a complete pipeline |
| Explain Kafka Reliability and Offset Recovery | Include retained events in recovery |
| Defend a Schema Decision Through a Real Technical Challenge | Explain evidence and migration trade-offs |
| Implement map serialization and deserialization | Make encoding assumptions explicit |
Use the schema integrity question to rehearse a change proposal with one writer/reader matrix, one replay counterexample, and one rollback condition.
Sources and Further Reading
- Confluent: Schema evolution and compatibility
- Apache Avro 1.12: Specification
- Confluent: Schema Registry API
Checked September 10, 2026. Local examples use Apache Avro 1.12.0. No Kafka cluster or Schema Registry service was deployed for these tests.