In a consumer-driven contract test, what does the recorded contract assert about the provider, and what does it deliberately not check?
answer
- Written by the side that consumes
- Only the fields the consumer reads
- Matchers instead of literal values
- Replayed against the real implementation
- Proves they can speak, not correctness
basics
~20 sA consumer-driven contract records the requests one consumer sends and the response parts it actually reads, then asserts the provider can still produce them. It checks the shape of the boundary, not whether the provider's answers are correct.
solid answer
~50 sThe artefact is produced by the consumer side. While the consumer's own tests run against a stand-in for the provider, every interaction it needs is recorded: the request it sends, and the status, headers and body fields it actually parses. That recording is later replayed against the provider's real implementation, which must return a response satisfying each recorded expectation. The assertions are deliberately narrow — normally a matcher per field ("an integer", "a timestamp") rather than a literal value — so the provider can add fields, reorder them or change data without breaking anyone. What the contract does not check is whether the provider's answer is *right*: it proves the two sides can still speak, not that a figure was computed correctly. It also says nothing about endpoints no consumer recorded, or about consumers that never published a contract at all.
code
pseudocode · 19 linescontract from "billing-dashboard" to "meter-reading-feed":
interaction "unbilled readings for one meter":
given state "a meter with 3 unbilled readings exists"
request:
method GET
path "/meters/8841/readings"
query unbilled = "true"
headers accept = "application/json"
response:
status 200
body:
readings: eachLike({
meterId: matcher.integer(8841),
kwh: matcher.decimal(14.37),
takenAt: matcher.timestamp("2026-04-11T06:15:00Z")
})go deeper
Be ready to say in one breath who writes the contract, who verifies it, and that it asserts the shape of what the consumer reads rather than the correctness of the values.
Explain the two runs and why matchers rather than literals are recorded, and be able to name three things a green verification does not prove — correctness, unrecorded endpoints, and non-participating consumers.
An interviewer expects you to reason about scope: which of your real integrations this mechanism can cover, what it leaves to other checks, and how you keep contracts to what consumers genuinely parse.
Own the argument for adopting it at all: what agreement checking costs per team, why it moves feedback into each team's own pipeline, and where a schema or a shared environment is the better instrument instead.
## The artefact, not the ceremony A consumer-driven contract is a file produced by running the consumer's own tests. It is not a design document written up front, and it is not the provider's published schema. Each entry in it — usually called an *interaction* — records one request the consumer actually sends and the response its code successfully parsed. The file therefore describes exactly one consumer's usage of one provider, expressed as executable expectations that a machine can replay. The work happens in two runs, separated in time and usually in different pipelines. ### Run one — recording, on the consumer side The consumer's tests execute against a local stand-in that serves the responses the consumer's code needs. Because the stand-in is programmed from the same declarations that get written out, every recorded interaction is one the consumer demonstrably handled. If the consumer never reads a field, that field never appears in the file. If it never calls an endpoint, no interaction exists for it. This is the *consumer-driven* part: the contract's scope is bounded by what one consumer uses, not by everything the provider offers. ### Run two — verification, on the provider side The provider's build takes the published contract and, for each interaction, puts itself into the precondition that interaction names, feeds the recorded request into the real implementation through its real entry point, and compares the actual response with the recorded expectations. Nothing belonging to the consumer runs here — its code, its language and its release schedule are all irrelevant. Verification asks one question: can this build of the provider still produce something that satisfies this recording? ### What is actually asserted Two things, and both are narrow. - **The request the provider must accept**: method, path, query parameters, the headers the consumer sets, and the request body it sends. - **The response the consumer must be able to parse**: the status, the headers it reads, and — for each body field it reads — a *matcher* rather than a literal. "An integer", "a string", "a timestamp in the agreed format", "an array whose elements look like this". Matchers are what make the artefact durable. If a contract pinned `kwh: 14.37`, then any change to the provider's seeded data would fail a consumer that never cared about the number. The example value stays in the file so a human can read it and so the consumer's stand-in has something to return, but the assertion is on the type or pattern, not on the value. ### What it deliberately does not check 1. **Correctness.** A meter-reading feed could return the wrong kilowatt-hours for every meter and still verify green, because the contract only claims the figure is a decimal. Business correctness belongs to the provider's own tests. 2. **The rest of the provider.** Endpoints, fields and error paths that no consumer recorded are untouched. A green verification run is not a coverage statement about the provider's surface. 3. **Consumers who never published.** A team that integrates by reading the documentation and writing its own client is invisible to the mechanism. The contract set covers exactly the consumers who participate. 4. **Everything below the boundary.** Whether the two are network-reachable, deployed at compatible versions, or configured correctly in a given environment is not asserted by the replay; a separate release gate has to answer that. ### Why the narrowness is the value Because the assertion set is small, it is cheap to run and stable under unrelated change. Neither side needs the other to be running: the consumer records against a stand-in, the provider replays a file. Two independently deployed components can therefore be checked for mutual agreement in each team's own pipeline, at unit-test speed, on every commit. ### A worked example A four-person team owns a smart-meter reading feed with two consumers: a billing dashboard and a tariff-analytics job. The dashboard reads only `meterId`, `kwh` and `takenAt` from each reading; the analytics job additionally reads `tariffCode`. Between them they publish 37 interactions. When the feed team adds an `estimatedFlag` field, verification stays green — no matcher mentions it, and the consumers ignore what they do not read. When someone renames `kwh` to `energyKwh`, both contracts fail in the feed's own build, minutes after the commit, naming which consumer and which interaction broke. That is the whole payoff: a rename is caught by the team that made it, without either consumer being deployed anywhere. ### The misreading to avoid Candidates often describe verification as "running the two services together". It is the opposite: the value comes precisely from never running them together. The recording validates the consumer's stand-in against the real provider, which is what turns an otherwise unfounded stub into evidence.
- If the provider adds a new required field to a response, does verification fail?No. Recorded expectations name only the fields the consumer reads, so an added field satisfies every existing matcher and verification stays green. That asymmetry is intended: additive change is safe for existing consumers. It flips for requests — if the provider starts *requiring* a new request field that no recorded request sends, the replayed requests are rejected and verification fails, which is exactly the signal you want.
- Why record a matcher and an example value rather than just the matcher?The example serves the consumer side and the human reader. The consumer's stand-in must return a concrete body for the consumer's code to parse, so a value has to exist; it is also what makes the contract file readable as documentation. Only the matcher is asserted at verification, so the example may differ from anything the provider ever returns without causing a failure.
- What happens to a field the consumer receives but never uses?It should not be in the contract. If the recording is generated from the consumer's actual parsing, unused fields never enter the file. Teams that hand-write contracts often paste a whole response body instead, which silently converts the provider's incidental fields into obligations and produces failures on changes nobody depended on.
A contract is the shopping list one flatmate hands another: it names only what they will actually cook with, so the shopper is free to buy anything else without breaking dinner.
saying these in an interview costs you the question
- Says the provider team writes the contract from its schema
- Asserts whole literal response bodies, so any new field fails
- Claims a green verification proves the provider's answers are correct
- Believes the contract covers consumers that never published one
- Describes verification as running both services together
- Thinks an added response field must break existing consumers