Rift

High-performance Mountebank-compatible HTTP/HTTPS mock server written in Rust

Rift is a drop-in replacement for Mountebank that delivers ~20–150x faster throughput on typical workloads, and up to ~1,850x on large regex predicate sets — while maintaining full API compatibility. Use your existing Mountebank configurations and enjoy faster test execution.

Get Started View on GitHub


Why Rift?

Drop-in Mountebank Replacement

Rift implements the Mountebank REST API, allowing you to:

  • Use existing Mountebank configuration files without changes
  • Keep your current test infrastructure and tooling
  • Switch between Mountebank and Rift transparently

Blazing Fast Performance

Built in Rust with async I/O, Rift delivers exceptional performance:

Feature Mountebank Rift Speedup
Static stub (first match) 7,240 RPS 209,192 RPS 29x faster
Regex (100th pattern) 110 RPS 201,067 RPS 1,821x faster
JSONPath predicates 4,586 RPS 190,329 RPS 42x faster
API stub — no match (404) 1,376 RPS 204,358 RPS 149x faster
Complex predicates 4,884 RPS 185,867 RPS 38x faster

Apple M4 laptop, 50 connections, median of 3 repetitions, 2026-09-17. On a 16-vCPU AMD EPYC server the same suite reaches 325k RPS and 6,160x on regex — but Mountebank is slower there, so the M4 figures above are the conservative read.

See the performance page for both hosts, the full suite, and the method.

Full Feature Compatibility

Rift supports all major Mountebank features:

  • Imposters - HTTP/HTTPS mock servers on any port, including mutual TLS
  • Stubs - Request matching with responses
  • Predicates - equals, contains, matches, exists, jsonpath, xpath, and, or, not
  • Responses - Static, proxy, injection with behaviors
  • Behaviors - wait, decorate, copy, lookup, shellTransform
  • Recording - Proxy mode with response recording

And Then Some

Compatibility is the floor, not the ceiling. Rift adds the things you would otherwise build by hand on top of a mock server:

  • Fault Injection - probabilistic latency, error and TCP faults, declaratively
  • Scripting - Rhai and JavaScript engines, with a script check / script run CLI
  • Scenarios and Flow State - declarative state machines and a per-flow key/value store
  • Correlated Isolation - per-flow partitioning so parallel tests don’t collide
  • Front Door and Gateway - route many imposters through one listener
  • Intercept Proxy - TLS-MITM a hard-coded external host without mitmproxy, over HTTP/1.1 or HTTP/2, with WebSocket upgrades relayed to the real origin
  • TLS & Mutual TLS - HTTPS imposters that require and validate client certificates, plus a private-CA trust store for proxying
  • Response Templates - date tokens and the _rift.templated {{ }} grammar, no script engine needed
  • Stub Analysis and Debug Mode - find shadowed stubs, and see why a request matched
  • Embedding & FFI - run the engine in-process from Rust or any language over the C ABI

The Features section covers all of them.


Quick Start

# Pull the latest image from Docker Hub
docker pull zainalpour/rift-proxy:latest

# Run Rift (Mountebank-compatible mode)
docker run -p 2525:2525 zainalpour/rift-proxy:latest

Create Your First Imposter

# Create an imposter that responds to GET /hello
curl -X POST http://localhost:2525/imposters \
  -H "Content-Type: application/json" \
  -d '{
    "port": 4545,
    "protocol": "http",
    "stubs": [{
      "predicates": [{ "equals": { "method": "GET", "path": "/hello" } }],
      "responses": [{ "is": { "statusCode": 200, "body": "Hello, World!" } }]
    }]
  }'

# Test the imposter
curl http://localhost:4545/hello
# Output: Hello, World!

Using an Existing Mountebank Config

# Start Rift with your existing imposters.json file
docker run -p 2525:2525 -v $(pwd)/imposters.json:/imposters.json \
  zainalpour/rift-proxy:latest --configfile /imposters.json

Node.js Integration

For Node.js projects, use the official npm package:

npm install @rift-vs/rift
import { rift, imposter, onGet, okJson, times } from '@rift-vs/rift';

await using engine = await rift.embedded(); // or rift.connect(url) / rift.spawn()

const users = await engine.create(
  imposter('users').stub(onGet('/api/users/1').willReturn(okJson({ id: 1, name: 'Alice' }))));

await fetch(`${users.url}/api/users/1`);
await users.verify(onGet('/api/users/1'), times(1)); // throws with a diff on mismatch

Migrating from Mountebank? The Mountebank-compatible rift.create({ port }) API stays available as a permanent drop-in, so adopting the typed DSL above is incremental rather than a rewrite.

See the Node.js Integration Guide for complete documentation.

Java / JVM Integration

For JVM projects, use the official rift-java SDK. It runs the engine three ways — embedded in-process (Panama FFM, no Docker), connected to any running admin endpoint, or as a managed spawned binary — with a fluent DSL plus JUnit 5, Spring, and Testcontainers integrations.

<dependency>
  <groupId>io.github.achird-labs</groupId>
  <artifactId>rift-java-core</artifactId>
  <scope>test</scope>
</dependency>
try (Rift rift = Rift.embedded()) {                  // or Rift.connect(uri) / Rift.spawn()
    Imposter users = rift.create(
        imposter("users").stub(onGet("/api/users/1").willReturn(okJson("{\"id\":1}"))));
    // point your system under test at users.uri(), then assert:
    users.verify(onGet("/api/users/1"), times(1));
}

See the rift-java documentation for the full feature surface, and the BOM for version-pinning every module at once.

Go Integration

For Go projects, use the official rift-go SDK. It runs the engine three ways — embedded in-process, connected to any running admin endpoint, or as a managed spawned binary — with a fluent DSL plus testing.T helpers.

The embedded transport loads the engine through purego rather than cgo, so CGO_ENABLED=0 keeps working: no C toolchain, and cross-compilation is unaffected.

go get github.com/achird-labs/rift-go
go run github.com/achird-labs/rift-go/cmd/rift-fetch@latest -version v0.17.0
func TestUserLookup(t *testing.T) {
    users := rifttest.Imposter(t, rift.NewImposter("users").
        Stub(rift.OnGet("/api/users/1").
            Return(rift.OKJSON(map[string]rift.JSON{"id": 1, "name": "Alice"}))))

    callSUT(t, users.BaseURL())

    rifttest.AssertReceived(t, users, rift.OnGet("/api/users/1"), rift.Once())
}

See the rift-go documentation for the full feature surface.

All four SDKs

Java, Scala, Node/TypeScript and Go are all officially supported and all replay the same conformance corpus. The Language SDKs section has the install snippet and hello-world for each, plus the transport and version-compatibility matrices.


Documentation

Getting Started

Concepts

Mountebank Compatibility (reference)

  • Imposters - Creating and managing mock servers
  • Predicates - Request matching (equals, contains, regex, jsonpath, xpath)
  • Responses - Configuring stub responses
  • Behaviors - Response modification (wait, decorate, copy, lookup, shellTransform)
  • Proxy Mode - Recording and replaying responses

Configuration

Features

Deployment

Reference

Embedding & Extension

  • Embedding & SPI - Embed Rift as a library, extend it via SPI traits
  • Embeddable Server - ServerBuilder, bindable admin/metrics
  • Extension Points (SPI) - Pluggable flow-store, journal, proxy store, sequencer, plus exchange-inspector, no-match, admin-authorizer and front-door observer hooks
  • FFI (C-ABI) - Drive Rift from any language

Project Status

The HTTP/HTTPS surface is stable and actively developed. Current status:

Area Status
HTTP / HTTPS imposters, including mutual TLS Stable
All predicates, static responses, behaviors Stable
Proxy mode (record & replay) Stable
JavaScript injection Stable
Fault injection, scripting (Rhai / JS) Stable
Scenarios, flow state, correlated isolation Stable
Front door, single-port gateway Stable
Intercept proxy (TLS-MITM, HTTP/2, WebSocket passthrough) Stable
Stub analysis, debug mode, hot reload Stable
Prometheus metrics, linting, terminal UI Stable
Embedding (Rust API, C ABI) and the four SDKs Stable
TCP protocol Not supported
SMTP protocol Not supported

License

Rift is distributed under the Apache License 2.0.