Skip to content

Contract

The question: will the other side still understand us after this change?

This is the only typology that catches a disagreement between two teams, and it is the one that makes the end-to-end suite shrinkable. Without it, the only way to know whether the consumer and provider still agree is to deploy both and try — which is what an integration environment is, and why it is always broken.

A provider tests its API against its own understanding. A consumer tests its client against a mock it wrote from the same documentation. Both suites are green. Both were written by people who read the same ambiguous sentence, and neither notices that one of them reads amount as minor units and the other as a decimal.

A contract test verifies both sides against the same artefact, so the misunderstanding has nowhere to hide.

Schema-first (specification-driven). An OpenAPI or AsyncAPI document is the contract; it exists before either side is built and is agreed between them. The provider is verified to conform to it, the consumer is verified against a mock generated from it. This is the default here, because the contracts already exist and are governed — see api-hub — and because it works when the provider does not know all of its consumers.

Consumer-driven. Each consumer publishes the subset it actually uses, and the provider verifies against every published expectation. More precise about what may safely change: a field no consumer reads can be removed, and the provider finds out mechanically rather than by asking around. It requires a broker, a publishing step in every consumer’s pipeline, and consumers who cooperate.

They compose. Schema-first for the shape, consumer-driven for the subset, when the extra machinery is worth it.

Not deployed. That is the point. The provider verification replays the contract’s interactions against the provider’s own process with its dependencies stubbed. The consumer verification runs its client against a mock generated from the contract.

Both sides therefore run in their own pipeline, in seconds, and the build that breaks belongs to whoever broke it. Compare that with the alternative — both deployed to a shared environment, a failure at 2am, and a half-hour argument about whose change caused it.

Everything the other side may rely on, and nothing else. The discipline is in the second half: a contract that describes the implementation freezes it.

In: endpoints and operations; request and response schemas with types, formats, required fields and enums; status codes; error shapes; authentication; pagination and idempotency semantics; the meaning of a field where a name is not enough (amount in minor units, in which currency, rounded how).

Out: which database is behind it; internal field names; performance characteristics (those are an SLO, checked by performance tests); anything a consumer would be wrong to depend on.

The value compounds when the pipeline can answer “is this change breaking?” without a human.

Safe for a provider: add an optional request field, add a response field, add a new endpoint, relax a validation rule, add an enum value if consumers were specified to tolerate unknown ones.

Breaking: remove or rename anything, make an optional field required, narrow a type or a range, change a status code, change a field’s meaning without changing its name. The last is the dangerous one, because no schema diff detects it — only a review does.

That the two sides are individually correct. A contract test proves they agree about the message; it says nothing about whether the provider computes the right number or the consumer displays it. Those stay with unit and integration tests on each side.

It also cannot catch anything about the assembled system’s behaviour under real conditions — the network, the latency, the ordering. That is what the small remaining end-to-end suite is for.

See API and contract tooling — Microcks for specification-driven mocking and conformance, Pact for consumer-driven contracts, Schemathesis for property-based conformance against an OpenAPI document.