The most expensive data incidents do not look like incidents. Nothing errors out. The rows arrive, the job completes, the model trains, and three weeks later someone notices the outputs changed.
A silent field change is the most common form of that failure.
Why it stays silent
A renamed column becomes nulls, and nulls are handled somewhere downstream by a default. A new category becomes an unknown value, and unknown is usually mapped to "other". A dropped field simply shrinks.
Every one of those paths is defensible alone. Together they mean the model trained on data that no longer matches the one described in the card.
Write the contract down
The contract is a small file: field names, types, allowed values or ranges, nullability, and the version. It sits next to the data, not in a wiki.
Then the loader checks it. A row that violates the contract is rejected with a reason, not coerced into shape.
Reject loudly, in private
Rejecting rows in production is alarming, so teams coerce instead. The right move is to reject into an exception queue, count them, and let a human decide.
A pipeline with an exception queue can be trusted. One with silent coercion cannot, no matter how green the dashboard.
Version the contract, not just the data
Every change gets a version and a date. Downstream jobs declare which version they expect, and a mismatch is a startup error rather than a surprise at month end.
Zovda ships each collection through Datuva with a contract that carries its version. The data research collection shows how the field list travels with the set.
Tell us which fields your pipeline depends on. We reply within one business day.
