Traffic Mirroring: Safely Test a New Backend

x32x01
  • by x32x01 ||
  • #1
Traffic Mirroring: Safely Test a New Backend
Replacing a production backend is not as simple as rebuilding the same endpoints in a new language and telling the frontend to switch.
Imagine you have a production PHP service handling real customer traffic, and you want to replace it with a TypeScript service. Your new endpoints may look identical, but you still need to prove that they behave correctly with the unpredictable requests, data, and edge cases generated by real users.
This is where Traffic Mirroring, also called Shadow Traffic, can help.



Why Unit Tests Are Not Enough​

Unit tests are important, but they only test the scenarios you expect.
You can write tests for different inputs, responses, validation rules, and edge cases. You can also create integration tests and run large test suites.
The problem is that production users will always find scenarios you did not think about.
For example, your frontend may send requests with combinations of parameters, data, timing, or user behavior that were never included in your test cases.
You could also compare the responses from the old and new services using manually created test scenarios, but that still does not represent the full variety of real production traffic.
This creates a simple question:
How can we test the new service against real production requests without actually sending its responses to users?



What Is Traffic Mirroring?​

Traffic mirroring means sending a copy of a real production request to a second service while the original request continues to the existing production service.
The existing service remains responsible for the response returned to the user.
The new service receives the same request in the background, processes it, and produces its own response. You can then compare the two results without changing what the customer sees.

A simplified flow looks like this:
Frontend → Old PHP Service → Response to Frontend

At the same time:
Frontend → New TypeScript Service → Response for Comparison Only
The frontend never receives the response from the new service during the testing phase.



A Real Backend Migration Example​

Suppose your company has a PHP API that has been running in production for years.
You decide to replace it with a TypeScript implementation.
The new service exposes the same API endpoints, but you do not want to immediately switch the frontend from PHP to TypeScript.
Instead, you enable traffic mirroring.

When a real request arrives, your infrastructure sends it to both services:
  1. The request goes to the existing PHP service.
  2. The PHP service processes it normally.
  3. Its response is returned to the frontend.
  4. A copy of the same request is sent to the new TypeScript service.
  5. The TypeScript service processes the mirrored request.
  6. Its response is captured but not returned to the user.
  7. The two responses are compared.
  8. Any differences are logged for investigation.
For example, imagine the PHP service returns:

Response 1
And the TypeScript service returns:

Response 2
The customer still receives Response 1, because the PHP service is the known production implementation.

Meanwhile, your comparison system checks whether Response 1 and Response 2 are equivalent.

If thousands or millions of real requests produce matching results, you gain much stronger evidence that the new service behaves correctly under real production traffic.



Why Real Traffic Is So Valuable​

The biggest advantage of traffic mirroring is that you are not guessing what users will do.
You are testing the new service with actual production request patterns.

That can expose problems such as:
  • Unexpected input combinations.
  • Missing edge cases.
  • Differences in validation.
  • Different handling of null or empty values.
  • Incorrect data types.
  • Differences in date or timezone handling.
  • Serialization differences.
  • Differences in database queries.
  • Performance problems.
  • Unexpected error handling.
This is especially useful during large migrations, such as moving an API from PHP to TypeScript, changing frameworks, rewriting a legacy service, or replacing an internal API implementation.



Traffic Mirroring Does Not Mean Blindly Copying Everything​

There is an important detail here.
You cannot always send a production request to the new service and assume it is safe.
Some endpoints perform side effects.

For example, a request might:
  • Create an order.
  • Charge a payment.
  • Send an email.
  • Update a database record.
  • Delete data.
  • Trigger another external API.
If the mirrored request performs the same action twice, you can create a serious production problem.

For that reason, mirrored traffic often needs special handling. The new service may use isolated databases, mocked external services, read-only access, or other safeguards that prevent duplicated side effects.
This is one of the most important parts of designing a safe traffic-mirroring system.



How Do You Compare the Responses?​

There is no single comparison method that works for every system.
A simple API might compare the response body directly.
However, some responses contain values that naturally change between requests, such as timestamps, request IDs, generated IDs, ordering, or other dynamic fields.
In those cases, you may need to normalize the responses before comparing them.
For example, you might ignore fields that are expected to be different and compare only the fields that represent the actual business result.

You should also record useful information when a mismatch occurs, such as:
  • Request ID.
  • Endpoint.
  • HTTP status code.
  • Relevant request parameters.
  • Response differences.
  • Processing time.
  • Error information.
This makes it possible for engineers to investigate mismatches instead of simply knowing that something was different.



When Should You Use Traffic Mirroring?​

Traffic mirroring is particularly useful when you are making a change where correctness matters and production behavior is difficult to reproduce completely in tests.

Common use cases include:
  • Migrating an API to another programming language.
  • Rewriting a legacy service.
  • Replacing a framework.
  • Migrating backend architecture.
  • Testing a new implementation against an existing production system.
  • Validating a new API before switching clients.
  • Comparing performance between two implementations.
It works especially well as a step between "the new service passes our tests" and "the new service now handles all production traffic."



The Safer Migration Path​

Instead of making a single large production switch, you can gradually increase confidence:
  1. Build the new service.
  2. Run unit and integration tests.
  3. Deploy the new service without making it responsible for user responses.
  4. Mirror real production traffic to it.
  5. Compare the old and new results.
  6. Investigate and fix mismatches.
  7. Repeat until the new implementation is sufficiently validated.
  8. Gradually move real traffic to the new service.
  9. Monitor the new service closely.
  10. Remove the old implementation after the migration is complete.
This approach gives you an additional safety layer between testing and a full production cutover.



The Main Idea​

Traffic mirroring lets you test a new backend with real production traffic while keeping the existing service responsible for the user's response.
That is what makes it useful for backend migrations.
Instead of trying to predict every possible scenario with tests, you can observe how the new implementation behaves against the traffic your users are actually generating.
The hard part is not simply duplicating the request. The real engineering work is making the mirrored execution safe and building a reliable way to compare the results.
And there are many ways to implement that comparison depending on your architecture, infrastructure, API design, and data.
00.webp

Frequently Asked Questions​

-------------------

Does traffic mirroring affect the user response?​

Normally, no. The existing service continues to generate the response returned to the user. The mirrored service runs separately for validation.

Is traffic mirroring the same as load balancing?​

No. Load balancing distributes requests between services that can serve users. Traffic mirroring sends a copy of the request to another service while the primary service remains responsible for the user response.

Can traffic mirroring be used for database writes?​

It can be, but it requires careful design. Mirrored requests can accidentally perform the same write twice. Isolation, read-only access, mocked dependencies, or other safeguards may be required.

Is traffic mirroring a replacement for unit tests?​

No. Unit and integration tests are still important. Traffic mirroring complements them by exposing the new service to real production request patterns.

What happens when the old and new responses are different?​

The mismatch should be logged and investigated. Depending on the API, the comparison may need to ignore expected differences such as timestamps or generated IDs.
 
Similar threads
x32x01
Replies
0
Views
4
x32x01
x32x01
x32x01
Replies
0
Views
59
x32x01
x32x01
x32x01
Replies
0
Views
72
x32x01
x32x01
x32x01
Replies
0
Views
67
x32x01
x32x01
Forum Statistics
Threads
1,028
Messages
1,033
Members
15
Latest Member
Mohamed
Back
Top