← Home ← Codex ← DEBT
Browse by Category
+ added · updated 7d
← Back to glossary

API Contract Testing

API Design Advanced
debt(d5/e5/b5/t5)
d5 Detectability Operational debt — how invisible misuse is to your safety net

Closest to 'specialist tool catches it' (d5). The absence of contract testing is detectable by specialist tools like Pact, Dredd, OpenAPI-validator, and Spectral, which can identify missing or broken contracts. However, the lack of contract tests isn't caught by default linters or compilers — you need deliberate adoption of these specialized tools. Without them, breaking API changes are silent until deployment or production (d7-d9), but with the listed tools in CI it drops to d5.

e5 Effort Remediation debt — work required to fix once spotted

Closest to 'touches multiple files / significant refactor in one component' (e5). The quick_fix suggests adopting Pact for consumer-driven contract testing, but this isn't a one-line fix. It requires writing consumer-side expectations, setting up provider-side verification, potentially deploying a Pact Broker for team sharing, and integrating into CI pipelines. This touches multiple files across consumer and provider codebases, making it a significant but bounded refactor — not quite architectural rework (e7) but more than a simple parameterized fix (e3).

b5 Burden Structural debt — long-term weight of choosing wrong

Closest to 'persistent productivity tax' (b5). Contract testing applies to web/api contexts across microservices and imposes ongoing maintenance: contracts must be updated as APIs evolve, a Pact Broker needs to be maintained, and every new consumer-provider relationship requires new contracts. Tagged as microservices/api-design, this is a cross-cutting concern that affects multiple teams' workflows. It's not quite b7 (doesn't shape every change) but definitely more than b3 (affects multiple work streams, not just one component).

t5 Trap Cognitive debt — how counter-intuitive correct behaviour is

Closest to 'notable trap (a documented gotcha most devs eventually learn)' (t5). The misconception field states developers believe E2E tests are better than contract tests, leading them to skip contract testing entirely in favor of slow, flaky integration tests. Common mistakes include provider-driven contracts (instead of consumer-driven), overly specific contracts testing entire response structures, and not running contracts in CI. These are well-documented gotchas that experienced developers learn, but they contradict the intuition that more comprehensive tests (E2E) are always better.

About DEBT scoring →

Also Known As

Pact consumer-driven contracts contract test API verification

TL;DR

Consumer-driven contract tests verify that a provider API matches what consumers expect — catching breaking changes before deployment, without end-to-end tests.

Explanation

Consumer-driven contract testing (Pact): the consumer defines a contract (the requests it makes and responses it expects), the provider verifies it can fulfil those contracts independently. Unlike integration tests, both sides run independently — no shared environment needed. The Pact Broker stores and shares contracts between teams. Benefits: catches breaking API changes in CI without a shared staging environment, enables independent service deployments, and documents the actual consumer expectations. PHP: pact-foundation/pact-php, pest-pact.

Common Misconception

End-to-end tests are better than contract tests — E2E tests require a full environment and are slow and flaky; contract tests run in isolation, are fast, and give specific failure messages about which contract was violated.

Why It Matters

A provider team changing a field name from user_email to email breaks a consumer that was never told about the change — contract tests catch this in the provider's CI pipeline before deployment.

Common Mistakes

  • Provider-driven contracts — the provider dictates what it sends, not what consumers need.
  • Not running contract tests in CI — contracts only help if violations are caught automatically.
  • Overly specific contracts — test the fields you use, not the entire response structure.
  • No Pact Broker — contracts stored locally cannot be shared between teams.

Avoid When

  • A single team owns both consumer and provider and deploys them together — integration tests are simpler.
  • The API surface changes so frequently that maintaining contracts costs more than the bugs they prevent.
  • Simple internal SDKs where the provider and consumer share the same codebase and test suite.

When To Use

  • Services owned by different teams or deployed independently — contract tests catch provider changes before they reach staging.
  • Public or partner APIs where breaking changes have downstream cost and manual coordination is slow.
  • CI pipelines between microservices to get fast feedback without spinning up the full environment.

Code Examples

💡 Note
The Pact consumer test defines exactly what fields and status codes the consumer depends on — the provider can add fields freely but cannot rename or remove what the contract specifies.
✗ Vulnerable
// No contract testing — breaking changes discovered in staging:
// Provider renames 'user_email' to 'email' in v2
// Consumer teams never notified
// Integration test catches it... in a 2-hour E2E test run
// Fix: roll back provider deployment, coordinate change
// Cost: 4 hours of engineer time
✓ Fixed
// Pact consumer test:
$builder->given('user 42 exists')
    ->uponReceiving('a request for user 42')
    ->with(['method' => 'GET', 'path' => '/users/42'])
    ->willRespondWith([
        'status' => 200,
        'body'   => ['id' => 42, 'email' => 'alice@example.com'],
    ]);

// Provider verification runs against actual implementation:
$verifier->verify(); // Fails if provider returns user_email not email
// Caught in provider's CI — before deployment
// Fix: coordinate field rename with consumer teams first

Added 16 Mar 2026
Edited 31 Mar 2026
Views 74
Rate this term
No ratings yet
🤖 AI Guestbook educational data only
| |
Last 30 days
0 pings T 0 pings W 1 ping T 0 pings F 0 pings S 0 pings S 1 ping M 1 ping T 3 pings W 2 pings T 0 pings F 1 ping S 4 pings S 0 pings M 2 pings T 0 pings W 0 pings T 1 ping F 1 ping S 0 pings S 0 pings M 0 pings T 0 pings W 0 pings T 0 pings F 0 pings S 1 ping S 0 pings M 1 ping T 0 pings W
No pings yet today
Ahrefs 1
Amazonbot 14 Scrapy 11 Perplexity 9 Ahrefs 6 SEMrush 4 Google 3 Unknown AI 3 Meta AI 2 Claude 2 Bing 2 ChatGPT 1 Backlinks.com 1
crawler 54 crawler_json 3 pre-tracking 1
DEV INTEL Tools & Severity
🟡 Medium ⚙ Fix effort: High
⚡ Quick Fix
Use Pact for consumer-driven contract testing — the consumer defines what it expects, the provider verifies it satisfies those expectations without running the full stack
📦 Applies To
any web api
🔗 Prerequisites
🔍 Detection Hints
Integration tests that spin up entire stack to verify API contract; no way to detect breaking changes before deploying
Auto-detectable: ✓ Yes pact dredd openapi-validator spectral
⚠ Related Problems
🤖 AI Agent
Confidence: Medium False Positives: Medium ✗ Manual fix Fix: Medium Context: File Tests: Update


✓ schema.org compliant