Skip to main content

3 posts tagged with "apis"

View All Tags

· 4 min read
Puneet Khanduri

A few days ago, we annouced a major update to Diffy and briefly mentioned the introduction of a powerful Request Transformation feature. Before we dive in, here's a bit of context on why we need different kinds of request transformation.

As your APIs evolve, you inevitably introduce breaking changes that make old requests (served by older versions of your APIs) incompatible with newer versions of your APIs. If the new API is genuinely doing something different than the old API then the old requests are no longer useful for any kind of testing and you can safely ignore them.

That said, it is truly unfortunate that you can't use old requests to test newer versions of an API when the underlying purpose of the API hasn't changed. You still want to know that the new API behaves like the old API - only now you need to "touch up" your old requests to turn them into new requests.

Here's different kinds of touch ups you can perform with Diffy 2.0:

Header Transformation

Many of customers mirror production traffic to Diffy to catch API regressions in their services. Replaying production traffic in test environments can lead to some problems like auth tokens not working in test environments - you need to override the headers in order for the traffic to be consumable in your test environment. e.g.

request => {
request.headers['auth-token'] = 'test-environment-token'

URI Transformation

Sometimes, the new code you want to test is expected to have the same functionality as the old code with a modified URI structure. Modified URI structures in the new code mean that old URI structures sampled from production environments will lead to 404 errors. In order to successfully replay and verify the expected behavior of the new code, you need to transform the old URI structures to new URI structures before sending the request to your new code.

request => {
// transform /api/1/* to /api/2/* e.g.
// /api/1/products/3465 to /api/2/products/3465

request.uri = request.uri.replace('/api/1/','/api/2/')

Body Transformation

Making schema changes to your APIs involves mapping old fields in your old code to new fields in your new code. This situation requires for you to rewrite the body of requests with your old schema to new your schema so that the request becomes consumable to your new code. With this necessary transformation, your new code will not be able consume production traffic.

request => {
// We have just refactored our code such that product objects that were previously consumed as
// { name: string, image_url: string }
// are now consumed as
// { id: string, imageUrl: string }
// i.e. the field 'name' has been renamed to 'id' and
// 'image_url' has been renamed to 'imageUrl' =
request.body.imageUrl = request.body.image_url
delete request.body.image_url

Bonus - Advanced Security and PII Scrubbing

Your production traffic contains sensitive data that can not be exposed to your test environments. This requires the requests to be scrubbed before being sent to your test targets.

request => {
// We want to redact an email deep inside the body of the request = ''

The above examples are simplified pseudocode for readability but the key takeawaye is that you can implement pretty much any transformation you can imagine to your request given the power of a scripting language at your fingertips.

Request Transformation

With Diffy, you can now inject request transformation logic in 4 places:

All - these transformation will be applied to requests being sent to candidate, primary and secondary.

Candidate - these transformation will only be applied to the requests received by candidate.

Primary - these transformation will only be applied to the requests received by primary.

Secondary - these transformation will only be applied to the requests received by secondary.

You can pick the places that you want to inject your transformation via the UI and then write and save the transformation:

Request Transformation

That's it! You can now send traffic to your Diffy instance and Diffy will apply your transformations to the requests before sending them off to the targets.

If you have any follow up questions please feel free to reach out to us via our Discord server or at

· 3 min read
Puneet Khanduri


Sn126 is proud to announce a major update to Diffy. But a quick history recap on how we got here.

Diffy was originally built at Twitter in 2014. That's almost 8 years ago! Just let that sink in. There were many technology decisions that were simply the result of being born at Twitter. e.g.

  1. Diffy was written in Scala.
  2. It used Finatra for API design and Finagle for networking.
  3. It was built to test Thrift APIs before it was generalized to test HTTP APIs.
  4. Twitter had just introduced Manhattan - Twitter's proprietary key-value store of choice. Any new services being built were using Manhattan.

Many of these technology choices were innately great. The core difference engine written in Scala could not and still can't be written as concisely in Java. Finagle offered a beautiful abstraction for networking that made it possible to implement and merge http support in a matter of days.

After open sourcing Diffy, we began receiving support requests from other engineering teams. We began to understand the world outside had much more diverse requirements. This eventually lead to the birth of Sn126.

To meet the new set of requirements from our customers, we decided to build a more advanced version of Diffy called Isotope. This was the time when the tech choices we had made at Twitter started turning into tech debt. Scala and Finagle could not catchup to Java and Spring Boot. Scala's build story never got any better and simple tasks like updating our Finagle dependencies ended up becoming time consuming work.

Meanwhile, most of our customers were using these other technologies along with Nodejs and Python. As we worked closely with their engineering teams, we experienced their best practices and started adopting them ourselves. Every time we would ship minor changes to Diffy, we would ponder what it would be like to revamp it with the most cutting edge tech.

Finally, the last straw was the uncertainty around Twitter acquisition and the damage it did to the stability of its open source technologies. With my former colleagues not being sure about having a job in a few months, how could I be sure about the maintenance and support of their open source code at Twitter.

As the case went to trial, we started working on all the changes we wanted to free ourselves from our accumulated tech debt and rewrite significant chunks of Diffy.

  1. We swapped out Finagle with Spring Boot and introduced significant new chunks of Java.
  2. We added MongoDB integration to eliminate all the memory pressure caused by keeping all the difference results in-memory.

Why did Diffy keep everything in-memory? Remember the story about Manahattan from earlier ... if Diffy were to have any storage, it would have to be Manhattan ... and you can't open-source something with a proprietary dependency ... so we decided not to have any storage at all!

  1. We rebuilt the UI from scratch using Typescript, React and implemented material design.

Coincidentally, by the time the Twitter-Musk deal closed on October 28th, we had already removed every Twitter open-source dependency from the code base.

There are many great features we have built in Isotope that we can now introduce to Diffy. We have already added request transformation capabilities that allow production requests to be sanitized and rewritten before being multicast to test targets. We will talk about that and others in the next post.

In the meantime, feel free to take the new Diffy out for a spin and do share your feedback. We are

· 3 min read
Puneet Khanduri


The most common reason (if not the only) for alerts is deploying new code to production APIs.

It’s always the new code that makes all the noise and wakes you up in the middle of the night — almost like a new born baby. By contrast, old code sits quietly in production minding its own business. If your production environment has been humming like a peaceful symphony for the past week, the chance that it will start throwing alerts in the next hour are slim to none.

So how do you make sure that your new code doesn’t break your production symphony?

If you are familiar with Diffy, you already know that comparing the behavior of your new code to your old code against production traffic is the best guarantee you can ask for.

Over the years, Diffy has helped many large tech-heavy engineering teams achieve their quality aspirations. While Diffy users continue to get tremendous value from Diffy’s UI, our larger enterprise customers have been seeking better integration with their existing observability stack.

We did this custom integration for some customers but always wanted something like OpenTelemetry to come along so we would no longer have to build and maintain custom integrations.

There are 3 aspects to observability and this is how Diffy leverages all of them via OpenTelemetry:


Diffy logs include important lifecycle events as well as traffic events for every sampled request sent to Diffy. These can now be seamlessly ingested into your favorite sink.



One of the most valuable things Diffy does is shred your traffic schema to analyze and aggregate differences observed at various nodes. This creates an interesting opportunity for you to receive schema-based metrics from Diffy.



Lastly, Diffy now exports traces to your favorite tracing backend for you to inspect all sorts of interesting metadata. e.g. The Diffy UI limits the number examples it shows to carefully manage storage constraints — you can now observe the request and all 3 responses within the traces.


The logs, metrics, and traces currently exported by Diffy are based on a survey of our existing users. Please feel free to open an issue and let us know if there is anything else you need in any of these dimensions.

Try it out! Checkout our Advanced Deployment guide to explore these cool dashboards for yourself. If you have any questions, please feel free to reach out to us for support at