A platform introduces consumer-driven contract testing between microfrontend producer teams and the teams that consume their props/events, running these tests in each producer's CI before deploy. How does this actually work in a microfrontend context, and what class of breaking change does it fail to catch?
answer
- consumer writes the spec, producer's CI verifies it
- Pact-style contract broker
- catches known-consumer breakage pre-deploy
- blind to unknown/undocumented consumers
- doesn't catch visual/timing bugs
basics
~20 sEach team that depends on another team's fragment writes down exactly what they expect from it, and the producing team runs those written expectations as automated checks before every deploy — so a breaking change gets caught in CI instead of in production. It can't catch a new team you didn't know was depending on you.
solid answer
~50 sConsumer-driven contract testing works by having each consuming team publish a lightweight, executable specification of the exact shape and values it expects from a producer's props/events — a 'contract' file, often generated from real interactions with a mock of the producer. The producer's CI pipeline pulls all known consumer contracts and replays them against the producer's actual output before every deploy, failing the build if any contract would be violated, which converts a class of cross-team runtime breakage into a CI-time failure the producing team sees immediately. What it fundamentally can't catch is breakage caused by a consumer that never published a contract — an unknown or newly-created consumer, or a consumer relying on undocumented behavior nobody wrote a contract for — because the whole mechanism is only as complete as the set of contracts it knows about; it also doesn't catch runtime integration issues unrelated to the data shape itself, like visual regressions or timing/race conditions between fragments.
go deeper
Can describe, in plain language, that contract tests are a way to check 'did I break something someone else depends on' before deploying.
Explains the consumer-writes/producer-verifies mechanism and that it runs in the producer's CI before deploy.
Clearly names the coverage gap (unknown/undocumented consumers) as the fundamental limitation and can distinguish it from other test types (visual, timing).
Designs the governance layer that keeps the set of known contracts complete over time (onboarding enforcement, audits) rather than relying on the testing tool alone.
## What consumer-driven contract testing is Consumer-driven contract testing (CDCT) is a testing pattern, most associated with tools like Pact, originally built for backend service-to-service APIs and adapted to the microfrontend context to solve exactly the cross-team-breakage problem described earlier: a producer's own unit and integration tests can only verify the producer behaves the way the producer's team believes it should, but they have no way to know what a *consumer* in a different repo actually depends on. CDCT flips the direction of test authorship: instead of the producer guessing what to test, each consumer team writes (often semi-automatically, by recording interactions against a mock or stub of the producer during their own tests) a concrete specification of the exact prop shapes it passes in and the exact event payload shapes it expects back. That specification — the **contract** — is a small, portable artifact (commonly JSON) that gets published somewhere both sides can reach, typically a shared contract broker or a package registry. ## What the producer's CI actually does The producer's CI pipeline then does something specific and mechanical: - before allowing a deploy, it fetches every known consumer's published contract and replays each one against the producer's actual current build — feeding in the props each contract specifies and asserting the event payloads/output match what each contract expects; - if the checkout team changes an event field in a way that violates the shell team's published contract, that mismatch is caught the moment the checkout team's own CI runs the contract verification step — before the change is deployed, and specifically before it becomes the kind of hard-to-trace runtime failure discussed earlier, where the error surfaces in a different team's fragment days after deploy. This is a real shift in *where* the failure is caught: from production, discovered by users or another team's on-call engineer, to the producing team's own CI, discovered by the person who made the change, with a clear diff showing exactly which consumer's expectation broke and why. ## The trade-off The trade-off is process and tooling overhead on both sides. - **Consumer teams** have to actually write and maintain contracts — an ongoing task that competes with feature work and can silently go stale if a consumer's real usage evolves faster than its published contract does. - **Producer teams** have to run contract verification as a required CI step, which adds pipeline time and, more importantly, adds a new class of build failure that isn't really "their" code being wrong so much as an external expectation they now have to design around, which can feel like a loss of autonomy if not framed correctly (it's the same trade discussed for versioning: less unilateral freedom in exchange for safety). - There's also a **coordination cost** in setting up the broker/registry infrastructure itself and getting every team to adopt the discipline, which is a genuine organizational rollout, not just a library install. ## What it fails to catch The fundamental limitation — and the answer to what this specifically fails to catch — is that CDCT is only as complete as its set of known, published contracts. A consumer that never wrote a contract (a new team spinning up a fragment that starts depending on an existing event without telling anyone, or an old integration nobody remembered to formalize when the platform rolled out CDCT) is invisible to the whole mechanism; the producer's CI will happily report green and deploy a change that breaks that unknown consumer in production, because nothing told it to check. This is a real, recurring failure mode in practice: CDCT catches *known* breakage brilliantly but gives false confidence about *completeness* — a team can start trusting "CI is green, so nothing downstream broke" when the more honest statement is "nothing downstream that told us about itself broke." A second, narrower gap is that CDCT verifies data shape and values, not runtime integration behavior more broadly: - it won't catch a visual regression where a fragment renders correctly with valid data but looks broken next to a sibling fragment, - and it won't catch timing or race-condition bugs where two fragments' events fire in an order the contract doesn't encode (e.g. fragment A assumes fragment B's mount event always fires before its own, but under network jitter it sometimes doesn't). ## How the gap plays out A concrete way this plays out: a platform team introduces Pact-style contract testing between a shell and five consuming fragments. Four of the five publish contracts and the discipline works exactly as designed — a checkout team's field rename is caught in their own CI within the first week. The fifth fragment, built by a team that joined the platform after the CDCT rollout meeting, never published a contract because nobody told them to, and continues silently depending on undocumented behavior. Six months later, a routine refactor breaks that fifth fragment in production, and the postmortem's actual root cause isn't "contract testing failed" — it's "contract testing was never asked to know about this consumer in the first place." The practical lesson is that CDCT needs to be paired with an onboarding/governance process (every new consumer must publish a contract before its first deploy, enforced by the platform, not left to team discipline) or the coverage gap silently reappears exactly where a new team is least likely to know it exists.
- How would you close the gap of 'unknown consumers never publishing a contract' at an organizational level, not just a testing-tool level?Make contract publication a governance requirement enforced at onboarding — e.g. a new fragment can't register with the shell or subscribe to a shared event bus without first publishing a consumer contract, checked by the platform team's tooling rather than trusted to individual team discipline. Pairing this with periodic audits (searching production traffic/logs for consumers of an event that have no matching published contract) catches drift after the fact.
- Why is CDCT usually preferred over the producer team just writing their own guesses at what consumers need, sometimes called 'provider-driven' contracts?Provider-driven contracts only test what the producer's team believes consumers need, which is exactly the blind spot that causes cross-team breakage in the first place — the producer can't know a consumer's actual usage without asking them. Consumer-driven contracts source the specification from the party with ground truth about their own dependency, which is what makes the test meaningful rather than a restatement of the producer's own assumptions.
It's like a landlord who only knows about the tenants who filed a lease — renovating based on those leases won't break any of them, but a subletter nobody told the landlord about can still get locked out when the plumbing changes, because the landlord never knew to check.
saying these in an interview costs you the question
- Believes contract tests passing means no downstream consumer can possibly be broken
- Doesn't distinguish consumer-driven from provider-driven contract authorship
- Can't articulate that the mechanism only covers consumers who published a contract
- Assumes contract testing also catches visual regressions or timing/race issues
- No mention of the ongoing maintenance cost of keeping contracts in sync with real usage