Skip to content

Format review guide

Avro Reader and Writer Schema Compatibility: Review Evolution Before Reading Data

Compare the writer and reader schemas in the direction a read will use. Record field changes, promotions, aliases, defaults, unions, and unresolved semantic questions instead of collapsing them into one compatibility badge.

Avro data is compact because the reader relies on a schema. That makes schema history part of the data handoff, not an optional comment. A reader may use a schema different from the one that wrote the bytes, but the result depends on the direction of the read and on the resolution rules. A successful resolution does not prove that a renamed field kept its meaning, that a default is truthful, or that a collection is authorized for a use.

Updated

On this page

Preserve the writer schema with the data

The source date shown in this guide identifies a documentation check on 22 October 2026, not an original publication date. Follow the citation for the Avro specification edition being discussed.

The Apache Avro, (opens in a new tab) says binary encoding omits type information, field names, and record separators. A reader therefore needs the writer schema, plus any reader schema used for resolution. Preserve both with the data. Do not store only the latest schema and assume it can reconstruct an older writer.

Preserve the writer schema with the data (table)
Evidence fieldWhat to preserveWhy it matters
Data artifactExact file, message batch, or controlled reference and digestIdentifies the bytes under review
Writer schemaSchema used to encode the artifact, not only the latest schemaAllows the reader to interpret the bytes
Reader schemaSchema the target application will useMakes resolution direction explicit
DirectionFor example, old writer to new readerPrevents a vague compatibility label
Schema identifierRegistry ID, version label, or explicit unknownConnects the pair to its source
Canonical-form referenceRepresentation or fingerprint with methodMakes comparison reproducible
Resolution resultPass, fail, not tested, or application reviewKeeps uncertainty visible
Semantic questionsUnits, code meanings, time rules, null meaning, defaultsSeparates format result from application meaning

If the writer schema is missing, mark the read blocked or unknown. A successful parse with a guessed schema does not prove that the original values were interpreted correctly.

Apply Avro resolution rules in the right direction

The specification calls the encoding schema the writer schema and the expected schema the reader schema. Record fields match by name, regardless of order. Writer-only fields can be ignored. Reader-only fields need a default or resolution errors. A default fills missing data while reading; it does not make an encoding field optional Apache Avro, (opens in a new tab).

Apply Avro resolution rules in the right direction (table 1)
Writer typeReader typeSpecification-level result
intlong, float, or doublePromotable
longfloat or doublePromotable
floatdoublePromotable
stringbytesPromotable
bytesstringPromotable
Any other unlisted pairSelected reader branchRequires a matching rule or fails

These rows describe schema resolution, not application safety. An integer-to-floating promotion can change validation or precision assumptions. String-to-bytes can change display or indexing behavior. Record those consequences separately from the Avro result.

Apply Avro resolution rules in the right direction (table 2)
Schema changeResolution observationApplication question
Reader adds a field with a defaultDefault can supply a missing writer fieldIs the default semantically safe for every older record?
Reader adds a field without a defaultResolution signals an errorShould the release be held?
Writer adds a field the reader lacksWriter value can be ignoredCan the application tolerate dropped evidence?
Reader renames a field with an aliasWriter name may map to reader nameDid the codebook meaning stay the same?
Writer sends an unknown enum symbolReader enum default may handle itDoes the fallback conceal a new state?
Both sides use unionsSelected writer branch resolves to first matching reader branchWhich branch is selected, and is it intended?
Only documentation changesDocumentation is ignored for resolutionWhat human documentation still needs review?

Aliases do not prove that meaning is unchanged. Compare a renamed field’s codebook and record the application decision separately. A default can preserve the read while hiding a new producer state.

Compare a safe synthetic schema pair

The following pair is synthetic and contains no real event, customer, location, or operational data. It widens a count, renames a field with an alias, and adds a defaulted field. The synthetic default is a fixture value only. It is not a truthful production default and must be replaced or held for application review before use.

Synthetic old writer schema

Compare a safe synthetic schema pair code example, JSON
{
  "type": "record",
  "name": "SyntheticEvent",
  "namespace": "example.synthetic",
  "fields": [
    {"name": "event_id", "type": "string"},
    {"name": "count", "type": "int"},
    {"name": "label", "type": ["null", "string"], "default": null}
  ]
}

Synthetic new reader schema

Compare a safe synthetic schema pair code example, JSON
{
  "type": "record",
  "name": "SyntheticEvent",
  "namespace": "example.synthetic",
  "fields": [
    {"name": "event_id", "type": "string"},
    {"name": "count", "type": "long"},
    {"name": "status", "type": ["null", "string"], "aliases": ["label"], "default": null},
    {"name": "source", "type": "string", "default": "synthetic"}
  ]
}
Compare a safe synthetic schema pair (table)
FieldObservationOpen question
event_idSame name and primitive typeIs the identifier meaning unchanged?
countint to long promotionCan consumers preserve range and units?
label to statusReader alias maps the old nameDoes the codebook use the same meanings?
sourceReader-only field with a fixture defaultWhat honest value applies to older records?

This pair is not proof that an implementation accepts every edge case. A real test needs the actual writer schema, reader, logical types, union branches, and representative synthetic values. Treat the fixture default as unresolved until the application owner supplies a truthful rule.

Record compatibility as a matrix, not a badge

Test each direction that the release process permits. Name which schema wrote the bytes and which schema read them before calling a result backward compatible.

Record compatibility as a matrix, not a badge (table)
Test caseWriter schemaReader schemaResult field
Read older dataPrevious releaseCandidate releaseDecode result, defaults, aliases, and semantic review
Read new data with an older consumerCandidate releasePrevious releaseWhether ignored fields can be tolerated
Replay a stored messageExact stored writer schemaCurrent consumer schemaResolution plus semantic transformations
Change a unionPrevious branch setCandidate branch setSelected branch and default legality
Change a logical typePrevious annotationCandidate annotationFormat result plus unit and precision review

Use states such as pass, fail, not tested, and requires application review. Parsing Canonical Form can distinguish schema changes that matter to readers from attributes such as documentation that do not. A fingerprint can support stable identification, but the specification warns that fingerprints are not security guarantees. Keep its algorithm and scope beside the identifier, not as proof of provenance, integrity, or permission Apache Avro, (opens in a new tab).

Keep schema compatibility separate from rights and the next step

A reader can resolve two schemas while the data still has personal or confidential content, incorrect labels, or out-of-scope records. Defaults can hide missingness, aliases semantic changes, and ignored fields evidence. Preserve the artifact, schema pair, direction, implementation version, and unresolved questions in a controlled worksheet.

Pair this review with the dataset version and change log for release lineage and the data provenance log for source, rights, processing, and exclusion evidence.

This article is not a serializer, registry, validator, or deployment guide. It is a static schema-resolution worksheet that keeps format observations separate from application and ownership decisions.

After the owner has a supported non-health scope, authority to describe the collection, and a schema-evolution evidence packet, the qualified appraisal request path may be a next preparation step. It does not test Avro schemas, approve compatibility, create a quote, match a buyer, issue a legal opinion, or grant a license. Keep raw payloads and sensitive field values within the owner-approved handling boundary.

Takeaways

  • Preserve the writer schema with every Avro artifact and name the reader schema used for the test.
  • Test direction explicitly; schema resolution is not one universal compatibility badge.
  • Record promotions, defaults, aliases, union branches, enum defaults, and ignored writer fields separately.
  • Use synthetic schemas and values before exposing real payloads, and never treat a fixture default as production truth.
  • Treat successful resolution as a format result, not proof of semantic correctness, rights, privacy, or legal clearance.

Sources

  1. Apache Avro: Avro 1.12.0 Specification (opens in a new tab)

Use the appraisal path after the schema-evolution packet is organized.

It does not test Avro schemas, approve compatibility, create a quote, match a buyer, or grant a license.