Pact
Consumer-driven contract testing. Ensures API consumers and providers stay in sync without deploying both sides at once.
Overview
Pact is an open-source contract testing framework that implements consumer-driven contract testing (CDCT). Instead of testing APIs via integration tests that require both consumer and provider to be running, Pact lets consumers define their expectations in a contract file. The provider then verifies it can meet those expectations independently.
Pact is particularly valuable in microservices architectures where dozens of services communicate via APIs. It eliminates the "deploy everything to test anything" problem and catches breaking API changes before they reach production.
What it's used for
Pact is essential when:
- Microservices architecture: Many services calling each other's APIs — integration testing becomes a nightmare.
- Independent deployment: Consumer and provider teams deploy on different schedules.
- Breaking change prevention: Catch API contract violations in CI before they reach production.
- Bi-directional contracts: Use Pact Broker to manage and version contracts across teams.
Pros & Cons
Pros
- Eliminates brittle integration tests
- Enables independent deployment of microservices
- Catches breaking API changes in CI
- Supports multiple languages (JS, Java, .NET, Python, Go, Ruby)
- Pact Broker provides contract visibility across teams
Cons
- Learning curve: CDCT is a paradigm shift from traditional integration testing
- Not a substitute for all integration tests — some end-to-end validation is still needed
- Requires discipline: contracts must be maintained as APIs evolve
- Pact Broker adds infrastructure complexity
- Limited support for event-driven architectures (improving with Pact v4)
Platforms & Integrations
Pact runs on Windows, macOS, and Linux. It supports JavaScript, Java, .NET, Python, Go, Ruby, and Rust. The Pact Broker is a separate service (Docker or SaaS).
Pricing
| Tier | Cost | Includes |
|---|---|---|
| Open Source | Free | All language implementations, core features |
| PactFlow (SaaS Broker) | From $99/mo | Hosted Pact Broker, SSO, analytics, bi-directional contracts |
NZ Context
Pact is gaining traction among NZ fintech and SaaS companies that have moved to microservices architectures. Large NZ SaaS organisations — particularly those with globally distributed engineering teams — have publicly discussed contract testing as part of their quality strategy. For NZ teams transitioning from monoliths to microservices, Pact is typically introduced after the first "integration test nightmare" incident where a provider change silently broke a consumer in production. It requires genuine organisational buy-in because both consumer and provider teams must participate — which makes QA engineers who can champion the workflow across team boundaries particularly valuable in NZ job interviews.
Alternatives
- Spring Cloud Contract — Java/Spring-specific contract testing with similar concepts.
- OpenAPI + Schema Validation — Provider-driven approach. Less coupling but misses consumer-specific expectations.
- Mountebank — Service virtualization for stubbing dependencies during testing.
When to choose Pact
A quick decision guide for NZ teams evaluating contract testing options.
| Choose Pact when… | Choose something else when… | Combine with… |
|---|---|---|
| You have 3+ independent services communicating via REST or GraphQL APIs, deployed on separate pipelines | You have a monolith — contract testing adds overhead with no meaningful benefit when the consumer and provider share a codebase | Postman — for exploratory and manual API validation that contracts won't cover |
| Consumer and provider teams deploy independently and breaking changes have burned you before | Your API surface is entirely OpenAPI/Swagger-documented and you only care about schema conformance — OpenAPI schema validation is simpler to operate | Playwright or Cypress — for end-to-end flows that cross service boundaries and need real UI validation |
| Your CI pipeline needs fast, parallelisable API safety checks without spinning up a full integration environment | Your primary integration surface is event-driven (Kafka, SNS/SQS) — Pact's async support is still maturing; consider AsyncAPI or schema registry validation instead | WireMock — to stub third-party APIs that you can't write Pact contracts against (payment gateways, government APIs) |
| Multiple consumer teams (mobile app, web frontend, internal service) all call the same provider and have diverging expectations | Only one team controls both sides — Spring Cloud Contract is lower overhead when the provider team drives the contract rather than consumers | PactFlow Broker — to version and visualise contracts across teams; the open-source self-hosted broker works but PactFlow's can-i-deploy gate is worth the cost at scale |
What I would do
Practitioner judgment on tool adoption, team onboarding, and when to swap.
The bottom line: Pact earns its keep at the consumer-provider boundary where teams ship independently. Introduce it one contract at a time, gate deployments on can-i-deploy, and resist the urge to contract-test every field — specify only what the consumer actually uses, or you'll create a maintenance burden that kills adoption within six months.
Interview questions
Questions you are likely to get if you list Pact on your CV — with what interviewers are really testing for.
What is consumer-driven contract testing, and how is it different from integration testing?
What they’re really testing: Whether you understand the fundamental shift in who defines the contract and why that matters — not just whether you can recite Pact’s marketing copy.
Strong answer covers: The consumer defines its expectations as a contract file; the provider verifies that file independently without the consumer running; this eliminates shared integration environments. Contrast with integration tests where both sides must be deployed together, which creates scheduling dependencies and flakiness. Mention that CDCT tests the contract surface, not business logic — so it complements, not replaces, integration tests.
When would you choose Pact over OpenAPI schema validation for API contract testing?
What they’re really testing: Whether you can weigh trade-offs between tools rather than defaulting to "Pact is always better" — a sign of genuine experience over resume padding.
Strong answer covers: Pact wins when multiple consumers (e.g. a mobile app and a web frontend at a NZ SaaS company) use the same provider but have different field subsets — OpenAPI validates the whole schema, not what each consumer actually uses. OpenAPI schema validation wins when you want lightweight provider-side conformance checks without asking consumers to write tests. Mention PactFlow’s bi-directional contract feature as a middle ground.
You’re a QA at a Wellington fintech with 12 microservices. A provider team wants to rename a JSON field from account_id to accountId. How do you use Pact to manage this safely?
What they’re really testing: Whether you understand the can-i-deploy workflow and how Pact catches breaking changes in practice — not just theory.
Strong answer covers: The provider runs can-i-deploy against PactFlow before merging — if any consumer contract references account_id, the check fails and the rename is blocked. The safe path: provider adds accountId alongside account_id, consumers update their contracts one by one, and once all consumer contracts reference only accountId, the old field is removed. Mention that Privacy Act obligations at a NZ fintech make silent field renames especially risky in audit trails.
Your Pact consumer tests pass locally and publish a contract to PactFlow, but the provider verification step fails in CI with a 404 on an endpoint you know exists. How do you debug this?
What they’re really testing: Whether you can systematically debug Pact’s two-phase verification model rather than blaming CI or the other team.
Strong answer covers: Check the provider state setup — a 404 in verification usually means the provider state handler didn’t seed the test data correctly, not that the endpoint is missing. Verify that the base URL configured in the provider verification matches what CI actually starts. Check whether the contract in PactFlow is the version CI is fetching (tag/branch mismatch is a common gotcha). Pull the pact JSON and replay it manually with curl against the running provider to isolate whether it’s a data or routing issue.
How would you structure Pact in a GitHub Actions pipeline so that a provider can never be deployed if it breaks a consumer contract?
What they’re really testing: Whether you understand the full deployment safety loop — writing tests is only half the job; gating deployments is what makes Pact actually protect production.
Strong answer covers: Consumer pipeline: run Pact tests, publish contract to PactFlow with branch tag, run can-i-deploy --pacticipant Consumer --to-environment production before deploying. Provider pipeline: pull latest contracts from PactFlow, run provider verification, publish results back to PactFlow, run can-i-deploy --pacticipant Provider --to-environment production as the final gate before any deploy step. Mention that in NZ teams using GitHub Actions with environment protection rules, the can-i-deploy step maps naturally to a required status check on the protected branch.
Learn more
- PACT in CI — PACT Broker & Pipelines — Resync Bootcamp lesson on wiring can-i-deploy gates into GitHub Actions and GitLab CI
- Pact Official Site
- Pact Documentation
- Pact Foundation GitHub