MicroservicePatterns.com

Suggestions

  • PagePattern catalogAll patterns by category.
  • LabCircuit Breaker and Retries labCrash a dependency and tune the breaker.
  • LabSaga labFail a step and watch the compensations run.
  • PagePractice questionsScenario questions with explanations.
  • PageDesign reviewCheck your own architecture for anti-patterns.
Communication · Core

Consumer-Driven Contract Testing

The Consumer-Driven Contract Testing pattern has each consumer of an API or event publish what it relies on as a contract, and runs those contracts against the provider in its pipeline, so a breaking change fails a build instead of production.

Last updated

Use it when

  • Many teams provide and consume each other's APIs and events and release independently.
  • End-to-end test environments are slow, flaky or blocking releases.

Avoid it when

  • One team owns both sides and deploys them together. Normal integration tests are enough.
  • The API is public with unknown consumers. Versioning and compatibility rules work better there.

What is the Consumer-Driven Contract Testing pattern?

Each consumer, such as a BFF, a mobile app or another service, writes tests that describe the parts of a provider's API it uses. Those tests produce a contract that is shared through a broker. The provider's pipeline replays every consumer's contract against the provider and fails if any expectation is broken. The same works for event schemas.

What problem does the Consumer-Driven Contract Testing pattern solve?

End-to-end tests across many services are slow and flaky, and they need everything deployed at once, which defeats independent releases. Without them, a provider only finds out it broke a consumer after deploying. Contracts give fast, local checks that a change is safe for the consumers that actually exist.

How do you implement the Consumer-Driven Contract Testing pattern?

  1. Have each consumer write contract tests for only the fields and interactions it uses.
  2. Publish contracts to a shared broker, tagged with the consumer version and environment.
  3. Run all consumer contracts in the provider's pipeline, and block the deploy if one fails.
  4. Check before deploying that the versions about to run together have compatible contracts.
  5. Treat a failing contract as a conversation between teams, not a reason to delete the test.

When should you use it?

  • Many teams provide and consume each other's APIs and events and release independently.
  • End-to-end test environments are slow, flaky or blocking releases.

When should you avoid it?

  • One team owns both sides and deploys them together. Normal integration tests are enough.
  • The API is public with unknown consumers. Versioning and compatibility rules work better there.

What do you gain?

  • Breaking changes are caught before deploy
  • Fast tests without a full environment
  • Providers know exactly which fields are in use

What does it cost?

  • Every consumer must write and maintain contracts
  • Needs a broker and pipeline integration
  • Does not test behaviour beyond the contract

Who usually owns the Consumer-Driven Contract Testing pattern?

Platform and product teams. A platform team provides the building blocks, such as a library, a managed service or a standard, and each product team applies them in its own code and configuration. See how teams map to layers and patterns.

What are common mistakes with the Consumer-Driven Contract Testing pattern?

  • Consumers recording the whole response instead of what they use, so any change breaks the contract.
  • Contracts that are published but never checked in the provider's pipeline.
  • Using contracts to test business logic, which belongs in the provider's own tests.

Consumer-Driven Contract Testing in practice

Real-world example

REA Group

realestate.com.au ran a cloud-based Ruby microservices architecture and needed to know that services still worked together, without testing them all at once.

Pact, a consumer-driven contract testing tool, was conceived there in 2013 to help with integration testing. Contracts are generated from the consumers' tests rather than written by hand, so each system can be tested on its own with high confidence that they are compatible.

Source: Plugging Into the Future of API Contract Testing With Pact (Nordic APIs, 2023)

Example decision record
Context
Breaking API changes reach production because the shared end-to-end environment is slow and often broken.
Decision
Have consumers publish contracts for what they use, and verify all of them in each provider's pipeline before deploying.
Consequences
  • Breaking changes fail the provider's build.
  • Every consumer team writes and maintains its contracts.

Test yourself on Consumer-Driven Contract Testing

Communicationcore

The Orders team removes a field they believe is unused. Two days later, the mobile BFF breaks in production because it read that field. The shared end-to-end test environment had been broken for a week. What would have caught this?

2 questions involve this pattern. Practice all of them →

Done with Consumer-Driven Contract Testing?

Saved in this browser only. See your progress →