MockServer supports a very high request throughput from a single node. When you need high availability, horizontal scale beyond one node, or zero-downtime rolling updates, MockServer can run as a cluster so that all nodes share state.
There are two ways to cluster MockServer. For the full deployment guide — architecture diagrams, the -clustered image, Docker Compose and Helm examples, and a decision table — see Centralised Deployment.
The production-grade approach uses an embedded Infinispan state backend that replicates state synchronously across all nodes over JGroups. Expectations, scenario state, CRUD entity stores, and chaos profiles are visible on every node immediately after any write, and per-expectation Times match limits are enforced cluster-wide. No shared filesystem is required.
Clustering requires the mockserver-state-infinispan module on the classpath. The pre-built -clustered Docker image (mockserver/mockserver:clustered-{{ site.mockserver_version }}) bundles this module and its JGroups dependencies; the default image does not. It is enabled with three properties:
| Property | Env var | Default | Description |
|---|---|---|---|
| mockserver.stateBackend | MOCKSERVER_STATE_BACKEND | memory | Set to infinispan to enable the clustered backend (requires the mockserver-state-infinispan module). |
| mockserver.clusterEnabled | MOCKSERVER_CLUSTER_ENABLED | false | Set to true to activate the JGroups transport and state replication across nodes. |
| mockserver.clusterName | MOCKSERVER_CLUSTER_NAME | mockserver-cluster | Cluster identifier. All nodes that should share state must use the same value. |
Note: as with the file-based approach below, the request log and verification ring buffer are node-local by default — a verify() call only checks the node that received it. To make verify and retrieval of recorded requests aggregate across the whole cluster, enable cluster verify fan-in: set clusterVerifyFanIn=true and list the other nodes' base URLs in clusterVerifyFanInPeers (for example http://mockserver-1:1080,http://mockserver-2:1080). Each node then asks its peers for their local records and counts matching requests across the whole fleet before evaluating the verification (count-based verifications such as exactly/atLeast/atMost only; ordered verify sequences and the live dashboard traffic view remain node-local). If your control plane is authenticated (bearer token, JWT, or OIDC), also set clusterFanInPeerAuthToken (the same value on every node) to the credential each node should present to its peers — for example Bearer <jwt> — otherwise the cross-node queries are rejected and the verify/retrieve fails. The Centralised Deployment page covers this constraint and the full Docker Compose and Kubernetes/Helm setup.
A simpler alternative that needs no extra module is to have several non-clustered nodes share their expectations through a common read-write filesystem and identical persistence configuration. State is reconciled by writing to and re-reading the shared file rather than by live replication, so propagation is eventual rather than synchronous. This suits modest fleets where a shared volume is already available.
To create a file-based MockServer cluster all instances need to:
Each node could be configured as follows (adjusting the port as necessary):
MOCKSERVER_WATCH_INITIALIZATION_JSON=true \
MOCKSERVER_INITIALIZATION_JSON_PATH=mockserverInitialization.json \
MOCKSERVER_PERSIST_EXPECTATIONS=true \
MOCKSERVER_PERSISTED_EXPECTATIONS_PATH=mockserverInitialization.json \
java -jar ~/Downloads/mockserver-netty-{{ site.mockserver_version }}-no-dependencies.jar -serverPort 1080 -logLevel INFO
or
java \
-Dmockserver.watchInitializationJson=true \
-Dmockserver.initializationJsonPath=mockserverInitialization.json \
-Dmockserver.persistExpectations=true \
-Dmockserver.persistedExpectationsPath=mockserverInitialization.json \
-jar ~/Downloads/mockserver-netty-{{ site.mockserver_version }}-no-dependencies.jar -serverPort 1080 -logLevel INFO