Is Microservices the right architecture?
I received 3 requests today on Code Mentor related to Microservices and realized I was repeating similar advice in these concurrent chats. This is a consolidation of those conversations.
Firstly, when considering Microservices it is important to identify why you are making that decision. What metrics are you using to compare it to a traditional Monolith or SOA (Service-Oriented Architecture). Or were you simply looking to explore concepts like Serverless, Vendor Agnostic or Containers?
Do you understand the core principles that separate the different architectural patterns and are you using those differences correctly to justify your decision?
This article provides a concise overview of the underlying principals that separate the common patterns Best Architecture for an MVP: Monolith, SOA, Microservices, or Serverless?.
What if I told you all of these seemingly contradictory statements are true:
- You can design a Monolithic API that could be deployed into Serverless infrastructure
- A Monolithic API can be designed to scale well horizontally
- Many SOA implementations are still tightly coupled Monoliths
- You can design a Serverless solution that is still Vendor Agnostic
- Microservices is just a specific implementation of SOA across multiple domains
My experience of Microservices is not all bad, but in general most solutions that I am asked to consult on have been poorly thought out or the implementation was badly managed or sometimes it was just the wrong design choice in the first place. This post on Common Microservices Anti-Patterns sums up many of my negative experiences.
I recognise my experience is heavily biased because people don't reach out for help when they don't need it...
One clear point of difference that defines Monolithic and SOA solutions is that there is a central core where all the smarts are, it is where the bulk of the business logic is executed and maintained. The clients are dumb or thin. In Microservices there is no client / server relationship between the services, each of the services are smart and they manage and execute their own independant business logic and data access. Although we use the term micro these services are generally thick processes that have their own data access layer. The whole point is to avoid an overall central core altogether, there is no central processing, Microservices is generally regarded as edge processing, when you arrange the architecture maps like this you can see why:
Source: Examples and types of microservices
Clear scenarios where Microservices might not be the best fit for your solution:
- There is a single/central data store
- You have a small development team
- A single development team will be owning the entire eco-system
- You do not want to support multiple versions of any component in production
- You want tight control and knowledge over all components
- You expect all code to be accessible and executable from a single source code project/repository
The irony of Microservices is that the intention is to achieve simplicity, high performance, low cost and avoid technical debt for the smallest individual components. However, to do this the overall solution is split up into code that might be written in multiple languages, stored and managed in different source repositories and deployed to multiple cloud vendors. Overall it can become a poor performing, expensive eco-system where the knowledge about how to maintain, monitor and troubleshoot issues is not commonly shared but is divided amongst many members across many teams. Ultimately the risk is that we might achieve the highest overall level of technical debt and complexity of all possible architectural patterns.
For Microservices to work, each independent service must be a bounded context that can exist and operate on its own. Not only can each service be deployed independently, there must be value in doing so. We need to avoid analysing the eco-system as a whole, that is really the point, to allow it to grow unconstrained.
It takes a special mind-set for product owners to operate in a Microservice solution and importantly a decentralised approach to the management and implementation of the overall solution, if there is a single code repository or solution file, then this is often a red flag.
In a cloud-first world SOA is essential, Microservices is simply multiple SOA domains that can interact with each other. You may not need to buy into the hype of Microservices and instead realize that many of the concepts that we associate with this architecture are actually SOA concepts. Microservice Benefits and Drawbacks covers the evolution of SOA into Microservices and analyzes the factors that drove that change.
My general advice is to treat the concept of Microservices as if it is an anti-pattern, make a clear business case for your decision with careful consideration and analysis against other design choices. Make sure you have more justification than just that it is a current industry standard and you don't want to lock in to any vendor. Make sure Microservices solves the specific requirements of your overall solution and that you can easily define the separate bounded contexts, the separate business domains.
There are valid use cases for Microservices, I don't want to suggest that it is an outright anti-pattern, but it is so commonly implemented poorly that I will always treat this design choice with scepticism for smaller or inherently simple projects. IMO Microservices is one of those things that is guilty until proven innocent.