When One API Means Different Mocks for Each Team - Designing a Distributed WireMock Setup
Source: Dev.to
Where Single‑Instance WireMock Hits Its Limits
Running a single WireMock instance is straightforward:
- POST JSON to
/__admin/mappingsto register stubs. - Reset when testing is done.
Simple. But things change when you encounter scenarios like these.
1. Scaling out for load testing
When you place multiple WireMock instances behind a load balancer, you need to distribute the same stubs to all of them. You might think, “Why not share stub JSON files via Docker volumes?” That solves file distribution, but WireMock doesn’t automatically detect file changes. To pick up changes you must either:
- Restart each instance, or
- Call the Admin API to reload.
With N instances that’s N operations, which quickly leads to a custom script to automate the process.
2. Multiple teams sharing the same API mock but expecting different behavior
Consider a payment‑API mock:
- Team A wants to test primarily with success responses.
- Team B needs to focus on timeouts and error cases.
When sharing a single WireMock instance, stub overwrites become a constant battle.
3. The learning curve for creating and editing stub definitions
WireMock stubs are written in JSON, and getting URL‑pattern matching and response structures right requires reading the documentation. Not everyone on the team can write these JSON definitions fluently, so stub creation and maintenance tend to fall on a few specific members.
Existing Options and Their Limitations
I evaluated the existing options for this problem.
| Option | Pros | Cons |
|---|---|---|
| WireMock Cloud (commercial SaaS) | Distributed management, GUI | Cannot self‑host, cost concerns, security‑policy constraints |
| Custom scripts that call the Admin API | Works for simple sync | Adds cognitive load; still a manual step. One‑click GUI sync is preferable |
| Git‑managed JSON files + CI/CD pipelines | Elegant on paper | Too heavyweight for “tweak‑a‑stub‑and‑test‑it‑immediately” cycles (commit → push → CI → deploy) |
From these considerations I concluded we needed a self‑hosted tool with a GUI that provides instant deployment and centralized management of distributed instances. Thus, WireMock Hub was born.
Design Decision 1 – Why “Project” Is the Top‑Level Concept
The most important design decision in WireMock Hub was placing the project at the top of the data model.

Project
├── Instance (WireMock instance): 1..N
└── Stub Mapping: 0..N
In most mock‑management tools the instance is the top‑level concept – “this instance contains these stubs.”
In our environment, multiple teams needed different mock behaviors for the same API:
- Team A needed a payment‑API mock returning success responses.
- Team B needed one that simulated timeouts and server errors.
By making project the top‑level concept we gain:
- Parallel management of multiple behaviors for the same API – create separate projects such as “Payment API – Success Testing” and “Payment API – Error Testing,” each linked to its own set of instances.
- Environment switching becomes project switching – dev / staging / load‑test can be expressed as distinct projects; just change the instance URLs linked to each project to deploy the same stub set to different environments.
- Cross‑team interference is structurally eliminated – because projects are isolated, one team’s stub changes never affect another team’s environment.
Design Decision 2 – Why Full Reset + Redeploy
WireMock Hub’s sync process uses a full reset followed by a complete redeploy approach.

Sync flow:
1. DELETE /__admin/mappings on all instances (reset)
2. POST all stubs from SQLite to /__admin/mappings on all instances
You might wonder, “Wouldn’t differential sync be more efficient?” I considered it, but chose the full‑reset approach for two key reasons.
1. WireMock’s Admin API doesn’t guarantee a reliable view of the current stub state
If someone manually adds stubs via the API or another tool modifies the instance, the state Hub knows about and the actual instance state will diverge. Differential sync breaks down when this assumption fails.
2. An unknown state is the most dangerous state
In load testing we assume that mock responses are exactly what we defined. Any stray or leftover stub can cause flaky results, hidden bugs, or misleading performance metrics. By resetting first, we guarantee a clean slate before applying the authoritative stub set.
TL;DR
- Problem: Single‑instance WireMock doesn’t scale for multi‑team, multi‑environment load‑testing scenarios.
- Solution: WireMock Hub – a self‑hosted GUI that treats projects as the primary entity and synchronizes all instances via a full reset + redeploy cycle.
- Result: Teams can work in parallel, switch environments with a click, and trust that the mock state is always exactly what they defined.
Feel free to reach out if you’d like to try WireMock Hub in your organization or discuss the design further!
Design Decision 2 – Full Reset Before Sync
Running with “the state is probably correct” under differential sync undermines the reliability of test results.
The cost of a full reset is acceptable.
With a few hundred stubs, a full delete and re‑register takes only seconds. Since stub deployment isn’t a frequent operation, this brief wait is not an issue.
This is a trade‑off between correctness and efficiency, and in a mock environment correctness should take priority.
Design Decision 3 – Why No External Database
The choice of SQLite as the data store was driven by the principle of minimizing the barrier to adoption.
WireMock itself is a tool that sells on “start with a single docker run.” If its management tool required setting up PostgreSQL or MySQL, the adoption barrier would become too high.
With SQLite, no external database setup is needed. Data is persisted simply by mounting a Docker volume, backups are just file copies, and sharing data between teams is as easy as sharing the SQLite file.
# This is all you need for persistence
services:
wiremock-hub:
image: ghcr.io/ykagano/wiremock-hub:latest
ports:
- "80:80"
volumes:
- wiremock-hub-data:/data
Note: At large scale (thousands of stubs, dozens of teams using it simultaneously), SQLite’s concurrent‑write performance could become a bottleneck. For a WireMock management tool, write frequency isn’t that high, making SQLite sufficient for now.
WireMock Hub Overview
Here’s the architecture of WireMock Hub, reflecting the design decisions above.
┌────────────────────────────────────────────────────────────┐
│ WireMock Hub │
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
│ │ Frontend │ -> │ Backend │ -> │ SQLite │ │
│ │ (Vue 3) │ │ (Fastify) │ │ (Persistence)│ │
│ └──────────────┘ └──────────────┘ └──────────────┘ │
└────────────────────────────────────────────────────────────┘
│
│ Sync (Full Reset + Redeploy)
▼
┌────────────────────┼────────────────────┐
│ │ │
▼ ▼ ▼
┌──────────┐ ┌──────────┐ ┌──────────┐
│ WireMock │ │ WireMock │ │ WireMock │
│ Instance │ │ Instance │ │ Instance │
│ #1 │ │ #2 │ │ #3 │
└──────────┘ └──────────┘ └──────────┘
Key Features
- One‑click sync – Deploy stubs to all instances linked to a project with a single click. A full reset precedes deployment, ensuring no state inconsistencies.
- Test requests – Send requests directly from the GUI to verify stub behavior. The entire cycle of creating a stub → syncing → verifying can be completed in the browser.
- Stub generation from request logs – Convert actual requests sent to WireMock into stubs with one click, dramatically reducing the effort of writing JSON by hand.
Quick Start
The Fastest Way to Try It (All‑in‑One Image)
An image bundling both WireMock Hub and WireMock is available.
docker run -d -p 8080:80 ghcr.io/ykagano/wiremock-hub:latest
open http://localhost:8080/hub/
After starting, create a project and register http://localhost:8080 as a WireMock instance to start exploring all the features.
One Tool for Both Daily Development and Load Testing
Making projects the top‑level concept enables different use cases to coexist within a single tool.
- Daily development – Keep the all‑in‑one image running as a single instance and use it as a mock server for your development project’s stubs. Create, test, and verify stubs entirely from the browser, replacing Postman or
curl. - Load testing – Spin up multiple WireMock instances only when running load tests, sync the load‑testing project’s stubs to all instances at once, and shut them down when done.
The ability to handle these two fundamentally different use cases—everyday mocking and load‑test mocking—simply by switching projects is a direct benefit of placing projects at the top of the design.
GitHub:
Documentation:
Feedback and issues are very welcome!