Konrad Kowalski (rootsher)Principal Platform & Reliability Architect011010100101000100011111010111000011001100111101

Shadow Traffic: Testing Without Responding to the User

date
category
CI/CD
also in
Reliability Engineering
reading
2 min / 302 words

Canary still affects users.

Even if only 1% of traffic reaches the new version, that 1% receives its response.

Shadow traffic appeared for a different question:

text
can we show real traffic to the new version without using its response?

The stable version serves the user.

The new version receives a copy of the request.

Minimal model

The logic looks like this:

text
client
  |
  v
stable version -> response to client
  |
  +-- copy request -> shadow version

The user does not see the shadow response.

We look at:

text
logs
metrics
traces
response differences
execution time
errors

The simplest example in a test gateway:

js
const stableResponse = await fetch("http://api-v1/orders", request);

fetch("http://api-v2/orders", request.clone()).catch((error) => {
  logger.warn({ error }, "shadow request failed");
});

return stableResponse;

This is not a production-ready pattern.

It shows the mechanism: the response from the new version does not go back to the client.

What it is really for

Shadow traffic is useful when we want to see how a new version behaves under the real shape of traffic.

It fits:

text
reads
new search engines
new scoring algorithms
response comparison
performance tests
dependency validation

It is especially useful when synthetic traffic does not represent production.

Real traffic has strange headers, old clients, unusual payloads, and event ordering that tests often miss.

The largest problem: side effects

Not every request may be copied.

If the request performs a write:

text
creates an order
sends email
charges money
publishes an event
changes inventory

the copy can cause damage.

Shadow traffic requires control over side effects.

Possible approaches:

text
mirror only GET
block writes in shadow
separate test database
mock external integrations
idempotency keys
mark requests as shadow

What shadow traffic does not test

Shadow traffic lets the new version see real requests, but it does not test the full production behavior.

The user still receives the stable version's response, so we do not see effects that would appear only after real traffic takeover: client reaction, retries, session changes, browser-side cache, or follow-up requests that depend on the response.

The second boundary is cost. A traffic copy still consumes CPU, memory, network, and dependencies. If the shadow version is slower, the user does not feel it, but the infrastructure can already receive extra load.

That is why shadow traffic is mainly for comparing behavior under real traffic.

It does not replace canary, because canary tests the moment when the new version actually responds to the user.