โ† All guides

A pact-stub-server alternative for when the contract stub needs to be a backend

Credit where due: pact-stub-server does exactly what it says on the tin. It's the Pact Foundation's Rust tool that loads your Pact contract files and serves their interactions as HTTP stubs โ€” and it's actively maintained (v0.7.1 shipped June 2026, Pact specification v4 support). If your team runs Pact contract tests, it has genuinely nice machinery: it can fetch pacts straight from a Pact Broker (with bearer tokens and consumer/provider regex filters), -w watches pact files and hot-reloads them, and -s filters interactions by provider state so one server can play different scenarios. Nothing on this page changes any of that.

This page is about the moment a team points a frontend, a demo, or a manual QA session at it โ€” using the contract stub as a general-purpose dev backend. A pact file is a record of specific request/response pairs, and pact-stub-server replays it faithfully. Faithfully is the problem.

The walls (each one verified on v0.7.1, August 2026)

We loaded a plain two-interaction pact โ€” GET /products returning a two-record list and a POST /products with an exact body returning a canned 201 โ€” and drove it with curl. Every claim below is the actual observed behavior.

Wall 1: anything not in the pact is a 404 with an empty body. GET /products/1 โ€” the completely obvious single-record fetch next to our stubbed list โ€” answered 404 with content-length: 0. No JSON error payload, so res.json() throws before your error handling even reads the status. Every route, every ID, every edge case must literally appear in a pact file.

Wall 2: matching is exact unless the pact carries matching rules. GET /products?page=2 and ?limit=5 โ†’ 404, because the recorded request had no query string. POST /products with {"name":"Other","price":7} โ†’ 404, because the pact's body said {"name":"New thing","price":5}. (Pact matchers can loosen this โ€” but only if your consumer tests wrote them into the pact; hand-rolled or example-grade pacts rarely do. Extra request headers are fine โ€” we sent a surplus Authorization header and still matched.)

Wall 3: writes are theater. The matched POST /products returned its canned 201 {"id":3,โ€ฆ} โ€” and the next GET /products returned the same two records as before. Nothing persists; the 201 is a recording. That's correct for a contract stub, and useless for a demo where you create something and expect to see it.

Wall 4: no failure simulation at all. We catalogued the full --help: log level, file/dir/url/broker loading, port, CORS, TLS, provider-state filtering, watch mode. There is no latency flag, no error-injection flag, no status override. Testing spinners, timeouts and retry logic is out of scope.

Wall 5: browser calls need a flag, and misses are undiagnosed. OPTIONS preflight returns 404 unless you remembered -o/--cors โ€” so a browser fetch() POSTing JSON from another origin fails before the request even happens. And when a request doesn't match, the log says only No matching request found for path /products โ€” not what differed (body? query?), so you're diffing pact JSON by eye.

The 60-second switch: your pact's data, as a real backend

The response bodies in your pact files are seed data. One jq line lifts them into a db.json-style import โ€” this exact pipeline ran against this API before publishing:

# pull the list-response body out of the pact, wrap it as {db:{products:[โ€ฆ]}}:
jq '{name:"from-pact", db:{products:(.interactions[]
     | select(.description|test("all products")) | .response.body)}}' \
   pacts/web-app-products-api.json > db-from-pact.json

curl -X POST https://mockbird.mockbird.workers.dev/api/projects/import \
  -H 'content-type: application/json' -d @db-from-pact.json
# โ†’ {"id":"<PID>","adminKey":"โ€ฆ","baseUrl":"https://mockbird.mockbird.workers.dev/m/<PID>",โ€ฆ}

Now the walls are just gone:

curl https://mockbird.mockbird.workers.dev/m/<PID>/products/1   # single GET: 200, free
curl 'https://mockbird.mockbird.workers.dev/m/<PID>/products?price_gte=15'  # filters: free
curl -X POST https://mockbird.mockbird.workers.dev/m/<PID>/products \
  -H 'content-type: application/json' -d '{"name":"Other","price":7}'
# โ†’ {"name":"Other","price":7,"id":3} โ€” and GET /products now returns 3 records. It persists.
curl https://mockbird.mockbird.workers.dev/m/<PID>/products/999
# โ†’ 404 with a JSON body: {"error":"not found"}

No process to run, CORS (including preflight) on by default, and the URL works from a teammate's laptop, a deployed preview, or CI.

pact-stub-server concepts โ†’ Mockbird

pact-stub-serverMockbirdNotes
interaction response bodiesimported recordsjq โ†’ db.json import; ids/types inferred, data verbatim
one interaction per request variantstateful resourceslist/single/nested GETs, POST/PUT/PATCH/DELETE, filters/sort/pagination/search โ€” zero per-variant config
provider states (-s, state header)snapshots + X-Mockbird-Snapshotsame idea, per request: pin any request to a named data state; --empty-provider-state footgun doesn't exist
-w watch + edit pact filesedit records via the API/dashboardchanges are live immediately; no files to reload
-o/--corsCORS default-on incl. preflightverified: browser fetch works with no flag
exact request matchingmatch-free CRUD + _gte/_lte/_ne/_likeunknown paths are real 404s with JSON bodies
failure drills?mock_status=503, ?mock_delay=2000, ?mock_chaos=0.3, ?mock_seq=500,500,200they have no flags for this โ€” guide
fixed/odd payloadscustom routesany status/body/content-type/headers/delay + templating
Pact Broker fetch, token auth, consumer/provider filtersno equivalenthonest: if your pacts live in a broker, that workflow is theirs alone
contract verification against the real providernot our jobkeep Pact for contracts โ€” this page is about the dev-backend use case

Try it in 10 seconds (shared demo, no setup)

# query params that actually work โ€” no interaction variants written:
curl 'https://mockbird.mockbird.workers.dev/m/demo/products?sortBy=price&order=desc&limit=3'

# a real 404 with a JSON body where pact-stub-server sends 404-empty:
curl -i 'https://mockbird.mockbird.workers.dev/m/demo/products/999'

# the failure drills it has no flags for:
curl 'https://mockbird.mockbird.workers.dev/m/demo/products/1?mock_delay=2000'
curl 'https://mockbird.mockbird.workers.dev/m/demo/products?mock_seq=500,200&mock_seq_key=me2'
# โ†’ 500 first call, 200 after โ€” point your retry logic at it

Honest comparison

pact-stub-serverMockbird
Pricefree, open source (MIT)free while in beta
Purpose-built forreplaying Pact contract filesbeing a hosted mock backend
Hosted URL others can hitno โ€” localhost Rust binary / Docker you runyes โ€” 10,000 requests/project/day, no signup
Unknown path behavior404, empty body (verified v0.7.1)404 with a JSON error
Query params / new IDs404 unless in a pact interaction (or matcher)always work
Writes persistno โ€” canned responses onlyyes โ€” POST โ†’ GET it back
Latency / error / chaos simulationnone (full flag list catalogued)mock_delay / mock_status / mock_chaos / mock_seq / mock_ratelimit
Scenario switchingprovider states (strong)snapshots + per-request pinning
Pact Broker integrationexcellent โ€” its home turfnone
Works offlineyesno
Maintenanceactive (v0.7.1, June 2026)actively developed

Written by the Mockbird maker โ€” bias disclosed. Where pact-stub-server genuinely wins: it is the right tool for Pact contract workflows โ€” broker fetching with auth and filters, provider-state selection per request, watch-mode reloads, pact spec v4 โ€” and faithful exact replay is precisely what a contract stub should do. Keep Pact for contract testing; verification against the real provider is the whole point. Every behavioral claim above was verified by us in August 2026 against the v0.7.1 release binary (two-interaction v2 pact on :9123, requests as described); release date and maintenance status are from the pact-foundation/pact-stub-server GitHub releases and repo. If any of this changes, we'll update the page.

Full API reference in the docs. More guides: mountebank alternative ยท MockServer alternative ยท Hoverfly alternative ยท WireMock Cloud alternative ยท Prism alternative ยท Karate mock server alternative ยท testing loading & error states ยท free mock API tools compared. Create your API โ†’