Think twice before adding another language to your micro-services architecture
Tags: productivity, webdev, architecture, microservices
Published: 2020-06-11 14:23:50

When in startup mode, a very important thing is to be flexible. Your product isn’t defined well-enough yet and it can change frequently and drastically. We knew that and decided to use _Python_ – it’s simple and allows very fast development.

Business grew and we started having clients. With every new client, our understanding of the product would expand. Some features turned out to be more relevant than others, as they produced more value for clients. We started to understand what was our core product and began cutting irrelevant functionalities out.

## Changing focus

Next step was doing what we do – just better. How can we reduce our costs but deliver the same amount of value (or more). There are 3 components from the development aspect I think are relevant:
- _cost of development_ which is most influenced by how hard it is to create a product using the platform
- _cost of deployment_ defined by the cost to run the whole product. This relates to the code performance and technologies used,
- _cost of maintenance_ depends on how much expertise does someone need to have in order to maintain a product on the platform.

Python is great, but it has its limits. It is designed to be easy-to-use, while languages like _C_, _Java_, and _Go_ are designed to be performant.

Between those languages, Go is the new and cool kid and is loved by some of my colleagues, so we decided to check it out. The hypothesis was that it should easily beat Python performance-wise.

## Research: comparing Python & Go performance

We’ve taken one service called _Gatekeeper_ inside our platform which was our biggest bottleneck. It communicates with _MongoDB_ and _Kafka_ a lot, and those IO operations turned out to take the longest. That is the part we wanted to improve most.

Due to the nature of our product, the test was focused more on increasing throughput, with latency reduction being less important. We’ve identified 5 scenarios on _Gatekeeper_ that should be tested. In Python, we implemented a Sync and Async version. The Async one used _asyncio_ – Python’s newest library that allows implementing coroutines. Also, Go was limited to a single core to reproduce our production setup.

The results:

<IMAGE>

_Go_ turned out to be a clear winner in all 5 scenarios. When considering the frequency of each scenario happening in real life, *the expected throughput increase is around 450%*. That is great news for our _cost of deployment_.

## Is it worth switching?

For me, the formula to calculate if it’s worth switching is this:

_y = A × x<sub>dev</sub> + B × y<sub>depl</sub> + C × z<sub>main</sub>_

_x<sub>dev</sub>_, _y<sub>depl</sub>_ & _z<sub>main</sub>_ are values representing the impact of a solution to each cost component. _A_, _B_ & _C_ are weights – how important is it to reduce each cost. _y_ is the end result, how much does a solution cost considering our priorities. We’re trying to keep that as low as possible.

For example, at the beginning, we didn’t care that much about the _cost of deployment and maintenance_, so our formula could look like this:

_y = 0.75 × x<sub>dev</sub> + 0.1 × y<sub>depl</sub> + 0.15 × z<sub>main</sub>_

We could really focus on *reducing the _cost of development_*, not really caring about the other two.

Right now, I’d say things have balanced out a lot. The formula looks much more like this:

_y = 0.50 × x<sub>dev</sub> + 0.25 × y<sub>depl</sub> + 0.25 × z<sub>main</sub>_

Our main driver is still the _cost of development_, but the other two have increased significantly relative to it. That gives us a lot of incentive to consider changing things up.

## What are our options?

We could rewrite everything to Go. Unfortunately, it’s a bit unrealistic. It would take too long to learn Go properly and do the rewrite. It would also negatively affect our productivity. Our _cost of development_ and _cost of maintenance_ would skyrocket.

We could stay all the way in Python. We would keep _cost of development and maintenance_ low, but it keeps _cost of deployment_ too high.

The final option we could try is introducing Go where it matters most, while keeping the minimum impact on developers using the platform. Our micro-services architecture allows us to do just a partial rewrite in another language. We could try rewriting only the components that handle internal stuff not visible by developers. That should keep _cost of development_ somewhat low, but _cost of maintenance_ for the platform just increased, since now we have to maintain 2 languages.

## It’s never black or white

We will try to do a partial rewrite. If things go great, we could gradually switch to Go. There could be more suitable languages or implementations that would help even more, but we have to move forward. We can only guess how things will turn out. The best we can do is making reality checks often to learn if we made the right choice early (and pivot if we didn’t).

This post was originally posted on [my blog](https://devwayoflife.com/2020/06/11/when-is-it-ok-to-add-another-language-into-your-micro-services/). Consider subscribing 😊