--- title: Mock Drift Detection shortTitle: Drift Detection description: Detect when real upstream services have structurally changed compared to your mock stubs, catching status code mismatches, new or removed JSON fields, type changes, and header differences. layout: page pageOrder: 7 section: 'Mock Server' subsection: false sitemap: priority: 0.7 changefreq: 'monthly' lastmod: 2026-05-31T08:00:00+00:00 keywords: mock drift detection, stub validation, proxy mode, schema drift, contract testing, response comparison, api evolution ---

## What is mock drift?

Mock drift occurs when a real upstream service evolves (adding fields, changing response codes, modifying headers) but the mock stubs used in your tests remain unchanged. This leads to tests that pass against stale stubs but fail against the real service.

MockServer's drift detection automatically compares forwarded (real) upstream responses against your stub expectations and flags structural differences, giving you early warning that your mocks need updating.

## How it works

When MockServer forwards a request to an upstream service (in proxy mode) and there are also response-type stub expectations matching the same request pattern, MockServer compares the real response against each matching stub and records any structural drifts. The analysis runs asynchronously and never slows down the response path.

Drift detection is automatic -- no configuration is required. Simply have both forwarding expectations and response-type stub expectations for the same request patterns.

## What is detected

Drift Type | Description | Confidence
--- | --- | ---
`STATUS` | HTTP status code differs between stub and real response | 1.0
`SCHEMA_FIELD_ADDED` | JSON field present in real response but not in stub | 0.9
`SCHEMA_FIELD_REMOVED` | JSON field present in stub but missing from real response | 0.95
`SCHEMA_TYPE_CHANGED` | JSON field type changed (e.g. number became string) | 0.95
`HEADER_ADDED` | HTTP header present in real response but not in stub | 0.9
`HEADER_REMOVED` | HTTP header present in stub but missing from real response | 0.9
`HEADER_CHANGED` | HTTP header value differs between stub and real response | 0.85
`PERFORMANCE` | p95 response time exceeds the configured threshold | 0.8

Non-semantic headers (`date`, `x-request-id`, `content-length`, `transfer-encoding`, `connection`, `keep-alive`, `server`) are automatically excluded from comparison.

## Retrieving drift records

Use the `GET /mockserver/drift` endpoint to retrieve detected drifts:

    curl http://localhost:1080/mockserver/drift

Response:

    {
      "count": 2,
      "drifts": [
        {
          "expectationId": "abc-123",
          "driftType": "STATUS",
          "field": "statusCode",
          "expectedValue": "200",
          "actualValue": "422",
          "confidence": 1.0,
          "epochTimeMs": 1717145600000
        },
        {
          "expectationId": "abc-123",
          "driftType": "SCHEMA_FIELD_ADDED",
          "field": "$.newField",
          "confidence": 0.9,
          "epochTimeMs": 1717145600000
        }
      ]
    }

### Filtering

Filter by expectation ID:

    curl "http://localhost:1080/mockserver/drift?expectationId=abc-123"

Limit the number of results (default 50, max 500):

    curl "http://localhost:1080/mockserver/drift?limit=10"

## Clearing drift records

To clear all recorded drifts:

    curl -X PUT http://localhost:1080/mockserver/drift/clear

Drift records are also cleared automatically when MockServer is reset via `PUT /mockserver/reset`.

## Storage

Drift records are stored in an in-memory LRU (least recently used) buffer with a maximum capacity of 1000 entries. When the buffer is full, the oldest records are evicted to make room for new ones.

## Semantic drift analysis (LLM-powered)

When you have a runtime LLM backend configured (see Configuration Properties), you can enable semantic drift analysis to automatically classify each structural drift as BREAKING, WARNING, or INFORMATIONAL.

Enable it with:

    -Dmockserver.driftSemanticAnalysisEnabled=true

When enabled, MockServer sends the drift details along with truncated stub and real response bodies to your configured LLM. The LLM classifies each drift and provides a one-sentence explanation. These are added to the drift records as `semanticSeverity` and `semanticExplanation` fields.

Semantic analysis is best-effort: if the LLM is unavailable or returns an error, drift records are stored with their original structural data only.

### Example response with semantic fields

    {
      "count": 1,
      "drifts": [
        {
          "expectationId": "abc-123",
          "driftType": "SCHEMA_FIELD_REMOVED",
          "field": "$.role",
          "expectedValue": "admin",
          "confidence": 0.95,
          "epochTimeMs": 1717145600000,
          "semanticSeverity": "BREAKING",
          "semanticExplanation": "Removing the role field will break clients that depend on it for authorization"
        }
      ]
    }

## Performance drift detection

MockServer can track response times per expectation and alert you when the p95 (95th percentile) response time exceeds a threshold. This helps detect performance regressions in upstream services.

Enable it by setting a threshold in milliseconds:

    -Dmockserver.driftResponseTimeThresholdMs=500

When the p95 response time for any expectation exceeds 500ms, a `PERFORMANCE` drift record is emitted. MockServer uses a sliding window of the last 100 response time observations per expectation to calculate percentiles.

Set to `0` (the default) to disable performance drift detection.