Sep 14, 2019

How to deal with APIs breaking change

Microservices brings down a big challenge around breaking contracts. This can impact the existing consumer, so my take has always been to have all minor changes in APIs to be backward compatible, whether it is exposed to internal or external clients. In case your change is big enough, then you may need to version your API. 

To have some kind of check around this, you can have a unit test suite that does the API integration test. Though this is easy, the challenge here is that the developer can fix it as per the new API definition and miss how a consumer might be using it. The next option is an automated contract testing (tools like PACT). This ensures that a pair of applications work correctly together as per the contracted document. This is definitely a great tool but on the other side, it does require effort in writing it and maintaining it. In my opinion, this is more suitable for application which has a high level of DevOps maturity. The next option is versioning, maybe the safest bet as it has very minimal risk and rolling back is also straight forward, but on the other side maintaining versioning for every minor change will very easily result in the messy application if it's frequently updated. The next and the final one which I am going to talk here is tools like swagger-diff. This is a simple tool that requires minimal effort to integrate it with your pipeline. The goal of this tool is to warn you if you have a breaking change. You can use the node module in the following way which will give you the differences

swagger-diff <old> <new>

Next, I am going to talk about types of breaking change and how to deal with that

Updating resource path

This can be done smoothly by providing support to both the old resource path and the updated resource path. The old resource path can redirect to the new resource path. In asp.net core you can use RedirectToActionPermanent which will result in 301 and the user will be redirected to the new action.

Adding Required Parameter 

Here you need to provide support to the resource with both old parameters and with the new parameter. You can do this by having two model objects one with old parameters for the old resource (which will make sure the existing contract is not breaking) and the other with new parameters. You can also mark the old one as obsolete is you don't plan to support it in the future.

The same can be a case when you add optional parameters that change the default behavior of invocation.

Changing Response Structure Or Response Code

We often consider additive changes are non-breaking as the consumer can safely ignore it until they upgrade their application, which is for most cases true, but there are cases where additive change can be breaking also like database truncation, etc.

There are other scenarios like change is rate-limiting rules, caching mechanism may also sometime be a breaking change.

Having to support multiple implementations also becomes challenging, so it's good to come up with a plan (with notice to consumers) to remove obsolete resources.