PACT in CI — PACT Broker & Pipelines
Local PACT tests are useful. PACT in CI is transformational. The PACT Broker stores contracts, tracks verification results, and powers the can-i-deploy command — which tells you definitively whether a service can be deployed without breaking any of its consumers.
1 The Hook
A Christchurch logistics company has 4 microservices using PACT. Contracts are stored as JSON files in each service’s repository. When the accounts-service updates its API, a developer manually checks which other services consume it and runs their PACT tests locally. Tedious. Error-prone.
One Friday, a developer forgets to check the reports-service. The accounts-service deploys. Reports break in production. On Monday, the team sets up a PACT Broker.
Now can-i-deploy is a hard gate in every CI pipeline. Before any deployment, it automatically checks whether every consumer of that service has verified the current contract. If one consumer hasn’t, the deployment fails. The manual check never happens again — because it can’t be skipped.
2 The Rule
Without a PACT Broker and can-i-deploy, you have contract tests. With them, you have contract governance. Only the second prevents production incidents.
3 The Analogy
A key registry.
Running PACT without a Broker is like having a key and a lock but no record of who has copies of the key. The Broker is the key registry. can-i-deploy is the question: “is my key still valid for all the locks that use it?”
You need the registry to answer that question. Without it, you have to ask every lock owner manually — and on a Friday afternoon, someone forgets.
4 Watch Me Do It
Option 1: PactFlow (hosted Broker, free tier):
Sign up at pactflow.io, get your API token, then set environment variables:
Option 2: Self-hosted Broker with Docker:
Consumer pipeline — publish contracts after tests:
Provider pipeline — verify contracts from Broker:
In the provider Verifier — fetch pacts from Broker dynamically:
can-i-deploy checks the Broker’s matrix of “which consumer versions have verified against which provider versions.” If PaymentsService on commit abc123 has not yet had its contract verified by CustomersService, can-i-deploy returns a non-zero exit code. The pipeline stops. No override. No warning. A hard stop.5 When to Use It
As soon as you have more than 2 services using PACT. PactFlow’s free tier supports up to 5 integrations — more than enough to start.
The can-i-deploy gate should block deployment, not warn. A warning nobody reads is just noise. If the command passes, deploy. If it fails, fix the contract first.
Publish contracts on every commit to a feature branch, not just main. That way the Broker has a record when feature branches are later compared during provider verification.
6 Common Mistakes
🚫 “I used to think: I can store pact files in the consumer’s git repo and check them manually.”
Actually: Manual checking breaks the moment you have 3+ services. The Broker automates the question “did every provider verify this contract?” Without it, PACT doesn’t scale. The Friday afternoon incident is a matter of when, not if.
🚫 “I used to think: can-i-deploy should warn, not fail the pipeline.”
Actually: Soft failures are how production breaks while tests “pass.” If can-i-deploy fails and the pipeline continues, you have removed the entire value of the gate. Make it a hard failure. The brief inconvenience of a blocked deployment is why you built contract testing in the first place.
🚫 “I used to think: I should verify all consumer pacts, not just those on the main branch.”
Actually: Verifying every pact from every branch — including abandoned feature branches — means you verify contracts that will never reach production. Use consumerVersionSelectors with mainBranch: true and deployedOrReleased: true. This limits verification to pacts that actually matter for deployment decisions.
7 Now You Try
A NZ bank has 3 services using PACT: PaymentsService (consumer of AccountsService), ReportsService (consumer of AccountsService), and NotificationsService (consumer of both AccountsService and CustomersService). Draw the dependency map and write the GitHub Actions steps for AccountsService’s provider pipeline that: runs provider verification fetching pacts from the Broker, publishes verification results, and gates deployment with can-i-deploy. Use consumerVersionSelectors correctly.
8 Self-Check
Click each question to reveal the answer.
Q1: What does can-i-deploy actually check?
can-i-deploy queries the PACT Broker’s verification matrix. For a given service version, it checks: has every consumer that is currently deployed to the target environment (or on main branch) had its contract verified against this version of the provider? If any consumer’s contract hasn’t been verified, can-i-deploy returns a non-zero exit code. It is not re-running tests — it is querying already-published verification results.
Q2: Why should consumer version selectors filter to mainBranch: true and deployedOrReleased: true?
Verifying every pact from every branch means the provider must satisfy contracts from feature branches that may never merge, be abandoned, or contradict each other. mainBranch: true covers the contracts heading for production. deployedOrReleased: true covers the contracts already in each environment. Together they limit verification to what actually matters for deployment decisions — and prevent unnecessary failures from speculative work.
Q3: What happens to the release process if a provider fails to verify a consumer contract?
The provider’s pipeline fails at the verification step. The provider version is published to the Broker with a failed verification result. When can-i-deploy runs for that provider version, it reads the failed result and exits non-zero — blocking deployment. The provider cannot deploy until the contract issue is resolved: either the provider fixes the regression, or the consumer updates its contract to match a negotiated new API shape (with both teams agreeing). This is the correct outcome — the gate is working as designed.
9 ISTQB Mapping
The CTAL-TA syllabus covers integrating automated tests into deployment pipelines as quality gates. The PACT Broker pattern is a direct implementation: test results (verification outcomes) are persisted centrally, and the gate (can-i-deploy) queries those results at deployment time. This separates test execution from deployment decisions — a principle the syllabus covers under CI/CD test strategy.
CTAL-TAE Section 6.3 — CI/CD integration: automated quality gates that block deployment on test failure. The can-i-deploy hard failure is a concrete implementation of what the TAE syllabus calls a “pipeline quality gate” — a non-bypassable check at the deploy stage.
10 Next Steps
You’ve completed the Contract Testing track. PACT contracts are written, the Broker is wired, and can-i-deploy is a hard gate. Next: apply the same rigour to your DevOps pipeline broadly, or explore Playwright in CI for end-to-end coverage.