The Biggest Microservices Mistake You Don’t Want to Make

The Biggest Microservices Mistake You Don’t Want to Make

Designing and architecting microservices in a correct way is an art, and one can master it with knowledge and experience.

When it comes to designing large and complex software systems, microservices architecture is the most common choice nowadays. If you design the microservices architecture in the right way, it certainly becomes a peace of mind. However, if you make some basic mistakes while designing microservices, it becomes a pain of mind in no time. Hence, it is important to not make some basic mistakes in the first place, so as you don't have to rectify and fix them at a later stage when your microservice is already in production and being used by a vast number of consumers.

In this article, we will look at one such biggest and most basic mistake you don't want to make with your microservices.

Designing and architecting microservices in a correct way is an art, and one can master it with knowledge and experience.

Nowadays, organizations are opting for a fail-fast approach and focusing on the rapid development of software systems, which enables them to go to market faster to beat the competition. That's the rapid Agile development in my viewpoint. Designing and developing microservices in such a highly Agile world is a challenge in itself. However, if you keep the basics right while designing microservices, you are way ahead in the game. Let us now take a look at the most common mistake that you must avoid while designing the microservice.

Let us understand it with an example. Consider a scenario wherein you have developed a microservice. It is up and running in the production environment. There are multiple consumers who are using the API(s) of your microservice for their systems and have successfully integrated them. They are pretty much happy with it. So far so good. Right?

Now, let's say, you have to enhance the existing API further by adding some new functionality to cater to the business requirement. Interestingly, now the challenge here is, you have to make your API(s) backward compatible so as the existing functionality remains untouched. The reason is, there may be a few consumers of your microservice who are still expecting the API to work as the older way. At the same time, there may be another set of consumers, who may want to consume the API with the latest changes introduced. Hence, it becomes essential to make the API(s) of your microservice backward compatible. If you don't make your microservice backward compatible, it can break your consumer's system. That's something you probably don't want to let happen.

Hence, In the initial phase of the microservices design itself, if you don't consider how to make your microservices backward compatible, then, it can give you a tough time going forward. And, this would be the biggest mistake you probably don't want to make with your microservices.

It would always be a good idea to make the API(s) of your microservice backward compatible with each new release of your microservice. And, to solve this backward compatibility puzzle, versioning the API(s) of your microservices is the solution.

Let us now understand when do we require API versioning, what is versioning of the API(s) and how to do the versioning of the API(s) of microservices.

When Do We Require API Versioning in Microservice?

In scenarios when you introduce breaking changes to the microservices API such as, you have changed the response format or you have changed the response type and so on, it is a must to have API versioning in place. 

Here is a quick example. Let's say, you have created one API in your microservice which returns the buyer's shipping address information details. 

Your API looks something like below. 

api/buyer/{id}/shippinginfo

In the first release, you were returning the address details all in one string (I am sure no one would do this trivial mistake; however, this is just an example) and the response of your API looked as following.

{

"id" : "buyer_1_id",

"address" : "some street, some city, some state, some country"

}

In the next release, you found that, instead of returning the whole address in single string, you should actually return it in more structured way. Hence, you took care of it and the API response now looks something like following.

{

"id" : "buyer_1_id",

"address" : {

    "street" : "some street",

    "city" : "some city",

    "state" : "some state",

    "country" : "some country"

}

}

Here, the end goal of the API remained unchanged. However, there was a major change in the response. Hence, in such scenarios, it is essential to have versioning of the API(s) in place, so as existing consumers who are expecting old responses are not affected. With that, it is now essential to understand what is versioning and how it could have helped here.

What is API Versioning in Microservice?

If we continue with the above example, we would call the first release of API version 1, and the next release of API version 2. The version basically helps to easily distinguish between old/new consumer requests and thus serve them according to what was supported for the specific version.

Version need not be numeric. You can select any meaningful version numbering format such as v1, version1, version-1, and so on. Let's use the version numbering format as v1, v2 in this article.

For our shipping address information API example, the consumer expecting an old response should call version 1 of your API, and the consumer expecting the latest response should call version 2 of your API. Now, how can we do that? Let's understand.

How to do API Versioning in Microservice?

When it comes to versioning the API(s), there are two possible ways at high-level. Here is a quick summary of the different flavours they support.

URL based versioning:

URI-based versioning.

Query string-based versioning.

Request header-based versioning:

Custom request header-driven versioning.

MediaType based versioning.

Both these approaches have plus and minus points. Let us now go through these approaches.

URL-based Versioning

One way to achieve API versioning is through API URL, wherein we specify the version number in the API URL itself. URL-based versioning can be achieved in two ways: URI-based versioning and Query string-based versioning. In your microservices code base, you should take care of how to cater to the API requests for different versions.

URI-based versioning

In URI-based versioning, we pass version information as a URI parameter. With this approach, our shipping address information API would look something like below:

api/{versioninfo}/buyer/{id}/shippinginfo

The consumer who expects an old response can call:

api/v1/buyer/buyer_1_id/shippinginfo

Query String-based Versioning

This is the second flavor of URL-based versioning, wherein we pass the version information as a Query string parameter. With this approach, our shipping address information API would look like the following:

api/buyer/{id}/shippinginfo?version=___

The consumer who expects an old response can call:

api/buyer/buyer_1_id/shippinginfo?version=v1

Request Header-based Versioning

Another way to achieve API versioning is through request header-based versioning, wherein the API URL remains untouched and we specify the version number as a part of request header information. 

Request header-based versioning can be achieved in two ways: Custom request header-driven versioning and MediaType-based versioning.

Custom Request Header-driven Versioning

In custom request header-based versioning, we specify the version number against the custom header in the request header information. Let's say we finalize our custom header name as API-VERSION. With this approach, our shipping address information API would look like following when the consumer wants to have an old response.

api/buyer/{id}/shippinginfo

API-VERSION: v1

MediaType-based Versioning

This is basically Accept header versioning, wherein we specify the MediaType in Accept header whenever we make an API call. In MediaType based versioning, we specify the version number against the Accept header along with the media type information in the request header information. 

With this approach, our shipping address information API would look like following when the consumer wants to have an old response.

api/buyer/{id}/shippinginfo

Accept: application/vnd.company.v1+json

Final Thoughts

Both the above versioning approaches have their pros and cons and it is challenging to conclude which one is the best. In my viewpoint, there isn't any best approach for API versioning. This decision should be carefully taken considering the practical aspects of your microservice development and implementation. 

In the Agile development world, API keeps evolving, and thus maintaining backward compatibility is a must to provide a seamless integration experience to your consumers. Hence, API versioning strategy and handling backward compatibility must be part of your design goals of microservice from the early phase.

ZippyOPS Provide consulting, implementation, and management services on DevOps, DevSecOps, Cloud, Automated Ops, Microservices, Infrastructure, DataOPS, and Security

Services offered by us: https://www.zippyops.com/services

Our Products: https://www.zippyops.com/products

Our Solutions: https://www.zippyops.com/solutions

For Demo, videos check out YouTube Playlist: 

https://www.youtube.com/watch?v=4FYvPooN_Tg&list=PLCJ3JpanNyCfXlHahZhYgJH9-rV6ouPro

If this seems interesting, please email us at [email protected] for a call.

Thank you for your time reading the article. Happy developing microservices.


Relevant Blogs:





 

Recent Comments

No comments

Leave a Comment