Microservices architecture is not one size fits all. While it can bring advantages in the areas of agility, scalability and resilience, it is vital for application leaders to know about the tradeoffs and costs that it can also bring. There are varying levels of service granularity that application leaders can chose from to ensure their firms and teams can fully realize benefits and advantages in balance with these tradeoffs.
Many application leaders assume that moving a large application to a microservices architecture is an all-or-nothing proposition. The technology industry has an extremely high-level of hype and excitement around this approach to application decomposition, so it is not surprising that many may not yet have a nuanced view of microservices. We have multiple service decomposition options available, allowing for a more strategic approach to dividing up a large application.
There are four levels of service granularity for application leaders to choose from: monoliths, macroservices, miniservices and microservices. They key distinction between these layers is the scope of functionality or data within each:
- A monolith is the state where everything exists within a small number of services. This is the default when no active service decomposition has been done.
- A macroservice generally has multiple service domains or business processes within the same application service codebase, server, and data store.
- A miniservice would only contain functionality for one service domain or business process. Miniservices could still share a data store or application server, or they could have an individual runtime layer and database.
- A microservice is reached when individual features of a service domain or business process have their own runtimes and data stores.
Individual microservices can add agility, but they can also add complexity and management overhead for an application team. How do we go about choosing the level of service granularity that gives optimal agility without incurring too many additional costs? Use a grouping principle where features that change together should stay together. The parts of the application that change the most frequently may be good candidates for microservices, but the slower moving features will likely be “agile enough” when still grouped together within a miniservice or macroservice.
Scalability is additional factor to consider when decomposing an application into multiple services. If your application relies on a scarce resource that can lead to a bottleneck, consider separating out that resource into a microservice that can be scaled independently. This is more cost efficient than scaling an entire monolith. In order do this scaling and deploying efficiently, strongly consider leveraging a container technology such as Docker or Kubernetes. Be aware there may be performance tradeoffs due to increased network traffic which could increase latency, and that each decomposition may introduce additional points of potential failure.
Advanced teams may wish to design for a resilient, self-healing application architecture. The goal of resilience is the successful operation of the application while one or more parts of it are in a degraded state. Microservices would be only one part of this pattern. Other essential parts would be resilient infrastructure (generally in the cloud), decoupled middleware like event brokers or service meshes, auto-scaling, deep monitoring, and automated recovery from failure events. Because of the increased granularity of microservices, additional points of failure are introduced into the application. Extreme caution must be used as using this style of application architecture can be very difficult to get right.
When deciding how to move an application towards microservices, it is vital to consider the technical and the business justifications for the increase in service granularity. Defaulting to a coarser granularity is likely the best path in many situations, with the push to fine-grained microservices limited only to those features which make the most sense based on requirements. Intelligently leveraging microservices can allow application teams to balance increased complexity with increased agility, scalability, and resilience for their applications.