Test Tools · API Testing

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).

Windows macOS Linux JavaScript Java .NET Python Go Ruby Rust REST GraphQL gRPC Message Queues Docker Pact Broker Jenkins GitHub Actions GitLab CI

Pricing

TierCostIncludes
Open SourceFreeAll language implementations, core features
PactFlow (SaaS Broker)From $99/moHosted 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.

If…
I was a QA engineer at CloudBooks joining a squad that owns a billing microservice with three consumer teams — the mobile app, the web dashboard, and an internal reporting service — and each team was independently maintaining their own WireMock stubs to fake the billing API
I would…
Pilot Pact with the one consumer team most burned by breaking changes — typically the mobile team, since they can't push a hotfix as easily as a web team. Get one contract written, verified in CI, and published to PactFlow. Show the provider team a failed can-i-deploy check before they merge a breaking endpoint change. That single demo usually converts the sceptics. Only then roll out to the other two consumers.
If…
I was working in a test team at Harbour Bank and the architecture team had mandated Pact for all new microservices, but developers were writing contracts that only tested happy-path responses and missing error states — meaning 400/422/503 responses were never verified
I would…
Establish a contract checklist: every consumer interaction must cover at least one success state, one validation error (422 with a specific error body shape), and one server-side failure (503). Add a linting step to the CI pipeline using Pact's JSON schema to flag contracts that only contain 200 interactions. A banking context has real consequences for ignored error states — a mobile app that doesn't handle a 422 correctly will silently drop a payment, which no audit team will accept.
If…
I was a senior QA at ListRight evaluating whether to replace the existing Karate API integration test suite with Pact, given that the integration environment was flaky and slowing down releases
I would…
Not replace Karate wholesale. Pact tests a different thing — it tests the contract, not the full integration behaviour. I'd keep Karate for the 15–20 critical end-to-end API journeys (search → listing → bid → purchase) that genuinely need both sides running, and introduce Pact for the high-churn internal service boundaries where breaking changes are most frequent. The goal is shrinking the Karate suite, not eliminating it — fewer flaky integration tests is the win, not zero integration tests.

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