From backend-engineering
Playbook for implementing consumer-driven contract tests (Pact) between backend services so API contract breaks surface in CI before they reach integration environments.
How this skill is triggered — by the user, by Claude, or both
Slash command
/backend-engineering:api-contract-testingThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
Use when two or more services communicate over HTTP/messaging and you want to catch contract breaks (missing fields, changed types, removed endpoints) in the individual service's CI pipeline rather than in a shared integration environment.
Use when two or more services communicate over HTTP/messaging and you want to catch contract breaks (missing fields, changed types, removed endpoints) in the individual service's CI pipeline rather than in a shared integration environment.
| Term | Meaning |
|---|---|
| Consumer | The service that calls the API |
| Provider | The service that serves the API |
| Pact | A JSON file of recorded interactions the consumer depends on |
| Pact Broker | Central registry that matches consumers to providers |
| Verification | Provider re-runs each pact interaction against its real code |
In the consumer's test suite (using the Pact SDK for your language):
# Python example (pact-python)
pact = Consumer("order-service").has_pact_with(Provider("inventory-service"))
(pact
.given("item SKU-99 exists in inventory")
.upon_receiving("a stock-check request")
.with_request(method="GET", path="/inventory/SKU-99")
.will_respond_with(
status=200,
body={"sku": "SKU-99", "quantity": Like(10)}, # Like = type-only match
))
Key matchers:
Like(value) — type only (any integer, not exactly 10)EachLike(template) — non-empty array of matching elementsTerm(regex, example) — value matches regexCommit the generated pact.json to the Pact Broker in the consumer CI job.
In the provider's test suite, replay every known pact against the real application (started in-process or via Docker):
# provider verification (pytest-pact)
@pytest.fixture
def provider_opts():
return {
"provider": "inventory-service",
"pact_broker_url": os.environ["PACT_BROKER_URL"],
"publish_verification_results": True,
"provider_version": os.environ["GIT_SHA"],
}
The provider CI job fetches all consumer pacts, runs each interaction, and publishes a pass/fail result. A failed verification blocks the provider's deploy.
Before any deploy, query the Broker:
pact-broker can-i-deploy \
--pacticipant inventory-service \
--version $GIT_SHA \
--to-environment production
Returns exit 0 only if every consumer whose pact is marked "required for production" has a passing verification against this provider version. Wire this as a required CI step before the deploy job.
Provider state handlers set up the preconditions described in given(...):
@provider_state("item SKU-99 exists in inventory")
def setup_sku99():
db.seed(sku="SKU-99", quantity=10)
@provider_state("item SKU-99 is out of stock")
def setup_sku99_oos():
db.seed(sku="SKU-99", quantity=0)
Keep states minimal — only what the consumer interaction needs, not a full fixture set.
| Approach | Catches contract break in | Team coupling |
|---|---|---|
| Pact (consumer-driven) | Each service's CI | Consumer drives the spec |
| Shared OpenAPI schema | PR lint | Both teams must coordinate |
| Integration environment | Shared test run | Slowest, most flaky |
Use Pact when teams deploy independently. Use schema sharing as a complement (not a replacement) — the schema documents intent; the pact proves the consumer's actual usage.
Like and EachLike for fields the consumer doesn't depend on.Guides completion of development work by verifying tests, detecting environment, and presenting structured options for merge, PR, or cleanup.
Enforces test-driven development: write failing test first, then minimal code to pass. Use when implementing features or bugfixes.
Guides creation and editing of skills using test-driven development with pressure scenarios and subagents to verify agent compliance.
npx claudepluginhub mcorbett51090/ravenclaude --plugin backend-engineering