Traditional contract testing points downstream: the provider publishes a schema; consumers check their compliance. Consumer-driven contracts invert the direction. Each consumer publishes an executable statement of what it sends and reads — endpoints, fields, formats — and the provider replays those expectations against its real implementation on every build. A change that breaks any consumer fails in the provider’s pipeline, minutes after the commit.

The inversion yields a second dividend: together the contracts map the interface surface in actual use — a field no contract mentions is demonstrably dead.

Consumer-driven contracts: two consumer teams publish executable expectations to a contract broker; the provider's CI fetches all current contracts, replays them against the real provider, and blocks the release when any expectation fails.

How It Works

  • Each consumer writes its expectations as executable examples: the request it sends, the response elements it reads.
  • Consumers publish these contracts to a shared broker, versioned per consumer and per environment.
  • The provider’s CI fetches all current contracts and replays them against the real provider implementation.
  • A failed expectation blocks the provider’s release and names the consumer it would break.
  • A deployment gate asks the broker which versions are verified against each other before promoting either side.

Failure Modes

  • An over-specified contract encodes fields the consumer never reads: provider changes fail the gate for data nobody uses.
  • Stale contracts from a retired consumer block provider releases until someone prunes them from the broker.
  • Contracts verify structure, not semantics: a provider passes every contract yet returns wrong values, and the gate stays green.

Verification

  • Provider CI verifies 100% of current consumer contracts on every commit; a red verification blocks promotion.
  • The broker’s compatibility matrix answers “can this version deploy?” for both sides before every release.
  • Integration defects that escape to staging or production trend toward zero; each escape gains a retroactive contract.
  • Provider-driven contracts (schema-first) — the provider publishes, consumers comply; simpler, but breakage surfaces on the consumer side and later.
  • Tolerant Reader — consumer-side tolerance shrinks what contracts must pin down; the two combine well.
  • Schema registry with compatibility rules — checks producer changes against evolution rules instead of real consumer expectations; cheaper, coarser.

Example

The checkout team consumes the pricing service’s quote endpoint and reads net, tax, and total. Its contract states: given a valid product id, the response contains those three numeric fields. When the pricing team renames tax to taxes, checkout’s contract fails pricing’s build within minutes — before anything deploys. The same week, pricing deletes the rounding_mode field without ceremony: no contract ever mentioned it.

References