Apache Avro logoGovernance

Nothing Silent: The Rules Behind Every Avro Round Trip

The dangerous transformation is not the one that fails.

Nothing Silent: The Rules Behind Every Avro Round Trip

The dangerous transformation is not the one that fails.

A failure is loud: someone sees a red response, reads an error, and fixes it before anything reaches production. The dangerous one succeeds — returning a clean, well-formed target schema in which a three-branch union has become a single-branch field, a decimal has lost its scale, and a closed enum has become an open string. No error, no warning; just a different set of promises than the one anybody agreed to.

Everything below exists to make that outcome impossible to reach quietly — the rules we apply when Avro is on either end of a translation.

Import is additive, and re-import does not duplicate

Bringing an .avsc into a project creates Types, Elements, and Taxonomies through the same layer as every other write in CoreModels, under the same per-project role checks. Writing a schema requires Admin on the target project; reading and stateless work require Viewer.

Re-encoding a schema into a project that already holds part of it upserts rather than duplicating: nodes are written by identity, and every relationship write is guarded against the edges already there, so importing the same .avsc twice does not leave you with two of everything. Import adds; it does not quietly reinterpret what is already governed.

Meaning changes are human-gated by construction

The mapping surface — where one schema is aligned onto another — is stateless. Nothing is written to the project; every call is inherently a dry run, returning the produced schema and the plan that produced it. When you want a result written, the map-import path offers a dry run first, returning a summary of what would be created.

That gate is structural, not procedural. A Viewer can explore translations all day and change nothing. Turning a translation into a change of governed meaning takes someone with write authority asking for it, after reading what the dry run said.

The plan is the artifact you review

Every translation produces a plan, and the plan is the reviewable object: it comes back in the response, it can be stored, and it can be replayed — the same plan against the same source produces the same output, a property we test rather than assert.

A plan can be produced by an authored mapping guide, by label-and-type inference against a target hint, or by an AI proposer. All three pass through one identical validation gate — the AI proposal earns no shortcut, and a stored plan earns none either. The gate checks that references resolve, named transforms exist, arities and types line up, no target id is produced twice, and no source node is both mapped and dropped. A failed proposal gets at most one repair attempt; if the repair also fails, the answer is rejection. The gate is never relaxed to flatter a proposal, and a plan's self-reported confidence carries no weight with it.

AI-assisted mapping is fenced in the ways that matter operationally: it requires Editor or Admin membership on the project, it requires a server-configured key, and it sends schema content to the Anthropic API server-side. We declare that rather than burying it, because a team governing proprietary schemas has every right to know which calls leave the building.

Lossiness is a success channel, and Avro exercises it

The most important sentence in our API documentation: a successful response does not mean nothing changed — it means it ran. What changed is in the lossiness list.

Each entry has a kind, a path, and a plain-English explanation. The four kinds: something dropped because the target had no home for it; a type approximated by a close-but-not-exact equivalent; a constraint relaxed because it could not be enforced; meaning narrowed or guessed.

Avro gives all four regular work. A union with more than one non-null branch narrows to its first branch, recorded with the alternatives declared dropped. An Avro map or a fixed is approximated as a string, recorded. A decimal loses its precision and scale, recorded. A field whose type is missing or malformed is approximated as a string rather than throwing, recorded.

At the record level the same discipline holds. Avro records carry no identity, so a record id is not written — a recorded relaxation, not a footnote. Avro links by embedding rather than by id, and we keep references as their target-id string so records survive a round trip: a documented divergence rather than a convenient silence. A field the schema does not know is dropped and reported, not swallowed. And Avro is single-type, so a record of another type is dropped with the reason stated.

A clean export and an export carrying six lossiness entries are very different artifacts. Our job is to make sure a reader can tell which one they have without reverse-engineering it.

Drift is evidence, not opinion

Governance that runs only at translation time has a blind spot, because reality moves after you look away. For streaming estates, the subjects export your registry tooling already produces can be audited against the governed model — read-only, with no credentials held and no broker connection opened.

The result is evidence with structure. Each finding carries a section, a severity, a code, the subject it concerns, a message, and a detail. Coverage findings name what exists in the estate that the governed model does not know about. Drift findings name the specific betrayals: a field removed, a field's type drifted, an enum narrowed, an enum widened, an allowed-value constraint removed. Conformance findings cover streaming hygiene, such as record fields carrying no documentation. The response also carries an error count, and a count above zero is the signal a build gate acts on.

That turns "I think the topic and the model disagree" into a named list a reviewer can accept or reject. Runs can be recorded to a history, so drift becomes a trail rather than an anecdote, and the latest state renders as a status badge.

Review, then deploy — always in that order

We generate artifacts. We do not deploy them. Registry-ready .avsc files come back to you as files; you review and register them through your own process, on your own schedule. Nothing we generate is applied to a running system on our say-so.

That is the posture in one line: we translate, we report honestly on what translation cost, and we leave every act of consequence in human hands.

To see the lossiness kinds and the audit findings on a schema of your own, start with the transform quickstart in the CoreModels docs.