Microservice architecture : A decoupling innovation or a recipe for disaster

 


     Microservices architecture has been seen as a silver bullet to decouple any sort of system without much effort and enhance the maintainability of that system as well. It does come with great potential. I am very careful with my words and hence I say "potential". It is great only as long as it is properly designed and implemented or else it will soon become a maintenance nightmare and a weird piece of code which is almost randomly demarcated into services making it a "poorly written novel by a great writer" which is a bigger disaster. But before we jump to what all things should be kept in mind to avoid such a disaster, let's quickly have a look at what a microservice architecture (MSA) offers us. 

     The key benefits that a well-drafted MSA offers are as follows :

  1. Loose coupling and high cohesion of code. In simple terms, "related" items should be together but "updating" one item should not be a mess for other items. If well designed, MSA achieves this brilliantly. 
  2. Avoiding SPOFs (Single point of failure).
  3. Separate scaling of services. Instead of scaling all the services together and using precious resources, we may scale only needed services and save resources and cut costs. 
  4. Better readability of code, and ease of maintenance. Clear separation of concerns and the ability for a team to work independently on the "larger project" by individually contributing to the "smaller project" or the microservice. 
  5. Great for Agile development and incremental releases. 
  6. Flexibility in terms of choosing a tech stack. One MSA could be in Jave while the other can be in Python or anything else as long as they have a way of communicating. Allows us to choose the best "tools" for the task.
  7. Easy extensibility and deployment ease. We can add a new microservice without affecting the existing code much and deploy individual microservice instead of the whole system. This also helps in version control of each "piece separately" ensuring higher availability. 
I can go on and on about this fairy tale where the protagonist (MSA) is all good and nice with no flaws but let us be real. The world is not black or white but grey. MSA is good only as long as it is designed and implemented well. Let me now walk you through the "grey" aspects of MSA. 
  1. If you are migrating from a monolith towards an MSA, how do you define which part of the code should reside in which microservice? The demarcation might seem obvious at first but is a very difficult job to do and if done wrong, you might have 'n' monoliths after splitting your '1' monolith. The decision is also complicated because each piece that you decide to split may now need to be contacted via a network call which is expensive and has limitations. 
  2. How do you do failure handling? MSA does remove a SPOF but it introduces MPOFs (multiple points of failure) if not written well. This can be like cancer spreading to your whole system. More the number of moving pieces distributed and scaling independently, the more the chances of one of them failing (In the real world, failures are inevitable. There is no way you can have a foolproof system. If you can, you would be really rich!).
  3. How do your microservices interact with each other? RPC or HTTP or web sockets or something else? Do they interact directly or via queues? Do they store state or are all stateless? These complications start adding up.
  4. The addition of new components (load balancers, circuit breakers, queues etc) is a costly affair in terms of time and money. 
  5. How do you avoid "over-engineering" and "engineering activism". It is very easy to get carried away as a team and start making too many microservices or try making the microservices too perfect or trying to achieve too much decoupling etc. MSA is not a magic wand which will get rid of all software development problems and we must understand our limitations and do a proper cost-to-benefit analysis before over-investing in this. There should and there is a saturation point.
    These are some of the drawbacks that one might have to face if MSA is used improperly. For understanding, let's try to visualize the "situation" via an HLD of a simple machine learning pipeline design. I must call out that the design is flawed in various places and is drawn only to explain the relevant points. Let us assume we have a monolith for this and the monolith reads CSV data, processes it, trains the model and deploys it to production from where the results are accessible via APIs. In a typical world, people usually come up with similar monoliths for getting a "quick and dirty" product up and running and eventually a "not so dirty product" ends up in production. The flow would look something like this :


Figure 1: A sample monolithic ML pipeline (Not perfect, only for illustration)

    Now, suppose the team is finally fed up with maintaining the "dirty pipeline" and its inability to scale and handle failure and decides to move to an MSA where each unit can scale independently and handle its own failures. They also want a bit of flexibility with the tech stack etc. They are really passionate about the pipeline and MSA and start moving to an MSA architecture. They work day in and day out to come up with this system (which to them is an engineering marvel!) :



Figure 2: The MSA-based redesign of that same pipeline as Figure 1

     They soon realize that this new system is able to scale a lot but has come up with a lot more maintenance work with all the new queues, load balancers etc in the picture. Also, they can't get that feeling of "perfection" any more as every now and then they come across pieces of code which they wish would have been in the "neighbouring service" instead of this place. Their documentation (and on-call support time) has increased and they need a larger team to handle the system. They did achieve a lot of decoupling but lost some cohesion because of the "not so well thought of separation of services". They are happy but not as much as they expected. They have realized that MSA is not a silver bullet. But they now have a lot to discuss over the team outings having a pizza! 

     This is one very oversimplified example of the boon and bane of MSA. In actual conditions, things are far more complicated and things can go far worse to the point that the original desire of reducing coupling and SPOFs etc may even remain unsatisfied. So the conclusion, as far as my understanding goes is that MSA is a great tool but needs a skilled hand to operate. It is easier said than done and if done the wrong way, it is a perfect recipe for a disaster. I am learning things as I go and I am open to suggestions and improvements in my work.

You can read more about MSA here :

Thanks!
Amrit Raj

Comments