Contract vs schema

A schema describes structure. A contract specifies behaviour and ownership.

The distinction matters because integration failures are rarely structure problems. The field exists. The type is correct. The format is right, most of the time. The failures happen at the edges: the record where the field is absent, the value that falls outside the expected range, the situation nobody thought to specify. A schema does not cover these. A contract does.

What a contract covers that a schema does not

Five things a data contract specifies beyond structure

Missing field behaviour: what happens when a required field is absent, reject the record, apply a default value, flag for human review, or retry after a delay.

Allowed value sets: not just the data type but the specific values that are valid. "String" is a schema answer. "One of: active, inactive, pending" is a contract answer.

Failure ownership: when a record violates the contract, who is responsible for resolving it, the sending system, the receiving system, or a shared queue with a named owner.

Change notification: what happens when either system changes a field name, deprecates a value, or adds a required field. The contract defines how changes are communicated before they break the integration.

Validity checks at runtime: the contract is not just a design document. It should be verifiable. The integration checks incoming data against the contract at runtime and surfaces violations as they occur rather than letting wrong data accumulate silently.

When contracts are absent

The four failure patterns that appear when two systems share data without a contract.

Failure 1

Format mismatches pass silently.

The sending system passes a date as DD/MM/YYYY. The receiving system expects YYYY-MM-DD. The integration does not validate the format. The date field is written with an incorrect value in every record. Reports built on the date field are wrong. Nobody catches it until a decision is made from a clearly impossible date.

A contract specifies the format for every field before the integration is built. A format mismatch found in the contract design phase is a one-line fix. The same mismatch found six months into production is a data cleanup project.

Failure 2

Missing fields fail silently or are skipped.

A required field in the destination is optional in the source. When records arrive without it, the integration either writes a null value into a required field (producing corrupt records) or skips the record entirely (producing gaps). Neither outcome alerts anyone.

A contract defines what happens for every field when it is absent: reject with a logged error, substitute a default, or flag for human review. The choice depends on the business impact, but the choice must be made before launch, not discovered in the data.

Failure 3

Value mismatches map to wrong categories.

The source system uses "Closed Won" as a deal status. The destination system uses "Won". The integration passes "Closed Won" to a field that only accepts "Won" or "Lost". The record is written with an unrecognised status value, or the field is left blank, or the integration applies a default that is incorrect for this record.

A contract maps every enumerated value from the source to its equivalent in the destination before the integration runs. Where no equivalent exists, the contract specifies what should happen, and who decides.

Failure 4

System updates break the integration invisibly.

A field is renamed in the source system during a platform update. The integration still refers to the old field name. Records arrive with the field absent. The receiving system writes nulls or skips records. The integration continues to report no errors because no errors are thrown, just missing data.

A contract documents which field names, API versions, and value sets the integration depends on. When the source system updates, the contract is the checklist that identifies whether the update affects the integration, before the update is deployed, not after.

When to write it

The contract comes before the code. If both sides cannot agree on it, the integration is not ready.

A data contract forces disagreements to surface at design time: writing it together reveals that the two teams assume different things about what the data means. On paper that costs a conversation; in production it costs a debugging project.