Skip to content

CONCEPT Cited by 1 source

Header-based mock switching

Definition

Header-based mock switching is the technique of using an L7 routing layer (an ingress proxy, a service mesh, or a sidecar) to inspect an inbound request header and route the call onwards either to the real external dependency or to a mock of that dependency — all for the same target service instance, in the same environment, based purely on per-request classification.

Contrast with the more common approach of standing up a separate deployment of the service that is statically wired to mocks.

Why a per-request switch

When a test cluster is shared between load tests and other test traffic (integration tests, feature-branch QA, developer spot checks), a statically-wired-to-mocks deployment forces an either/or choice: either all traffic in that deployment hits mocks, or none of it does.

A per-request switch lets both test types share a single deployment of the service:

  • Load-test traffic (header-tagged) is routed to mocked external dependencies to keep the test isolated and the external providers unbilled.
  • Integration-test traffic (no header) hits real dependencies for correctness verification.

This is the substrate Zalando's Payments department uses for its end-to-end load-test cluster (Source: sources/2021-03-01-zalando-building-an-end-to-end-load-test-automation-system-on-top-of-kubernetes):

"We leveraged header-based routing using Skipper, so a service can decide whether to use mocks or actual dependent service by examining if the request belongs to a load test or not."

Where the switch lives

The ingress-layer L7 proxy is the natural home because:

  • It already inspects headers for routing, auth, rate limit.
  • It already has a destination abstraction (real vs mock is just another pair of destinations).
  • It decouples the application from the test-type classification — app code doesn't change between tests and prod.

Skipper at Zalando — with its eskip DSL — expresses this as predicate-filtered routes: a predicate Header("X-Load-Test", "true") selects the mock backend; other requests fall through to the real backend.

The header

The header carrying the switch-signal is often the same load-test tag used for traffic-source tagging in traces — a single tag propagated from the load generator through the entire call graph, consulted both for routing and for observability stream separation. Reusing the tag avoids two classification schemes for the same semantic distinction.

Requirements

  • Complete tag propagation. If any intermediate service drops the header, all downstream services past that point lose the switch and may call real dependencies. Tracing libraries' baggage mechanisms + explicit mesh-level propagation lists are the usual implementation.
  • Mocks deployed in the same environment. The L7 proxy must be able to resolve the mock's backend URL. In Zalando's case, Hoverfly mocks run in NodePool A of the test cluster.
  • Abort-on-misclassification safety. A bug that routes load-test traffic to real dependencies ships real orders, real payments, real emails — the blast radius is severe. Upstream abort signals + kill switches remain required.

Limitations

  • Does not replace environment separation for production-safety — this pattern is suitable for test environments where both real and mocked dependencies are intended. Production should never be configured to switch on a header.
  • Routing-layer complexity grows. Every dependency gets a pair of routes. Maintenance cost scales with the mock surface.
  • Mock drift. Hoverfly mocks can silently diverge from the real dependency's current schema. The pattern doesn't solve this — it needs complementary contract verification.

Seen in

Last updated · 476 distilled / 1,218 read