Introduction 

Microservices are becoming one of the more popular architectural styles. As with any architectural choice, there are trade-offs to consider. Before deciding to adopt microservices, one should make an informed choice by weighing the benefits against the drawbacks in the context of the business and technical problems being addressed. 

In this article, I am going to present a brief overview of some of the benefits and drawbacks to be considered before settling on a microservice architecture.  

In business-related scenarios, software development is about adding business value, not about adopting technology for the sake of the technology. Sam Newman, a respected author and speaker on microservices states this clearly: 

You don’t win by doing microservices. The only person that wins if you do microservices is me because I sell books about microservices. You’re implementing microservices to achieve something. What is it you’re actually trying to achieve? It’s amazing how many people I chat to who can’t give me a clear articulation of why they’re doing microservices. It starts about having a real clear vision for what it is you’re trying to achieve. Then you can say, is microservices the right approach for this? Are we using microservices in the right way?”   

(See https://www.infoq.com/podcasts/monolith-microservices/ and https://samnewman.io/)  

Another well-known software architect, Chris Richardson, has identified several microservice anti-patterns that you should be aware of:

  • Magic pixie dust: believing that microservices will cure all of your development woes
  • Microservices as the goal: focusing on adopting microservices rather than improving the velocity and reliability of software delivery
  • Scattershot adoption: numerous groups with an organization adopt microservices and implement supporting infrastructure without any coordination
  • Trying to fly before you can walk: attempting to adopt microservices while lacking key development skills such as automated testing and the ability to write clean code
  • Focusing on technology: focusing on cool (deployment) technology rather than the essence of the microservice architecture: service decomposition and definition
  • The more the merrier: developing an excessively fine-grained architecture
  • Red flag law: keeping in place policies and processes that obstruct rapid, frequent and reliably software delivery.

(See https://microservices.io/microservices/general/2018/11/04/potholes-in-road-from-monolithic-hell.html )

What are Microservices and Monolith Systems?  

In this article, I’m considering the benefits and drawbacks of microservices compared to those of a monolithic system. Before beginning let’s understand what we mean by these terms. 

The following definitions are from an article by Martin Fowler and James Lewis, “Microservices – a definition of this new architectural term.”  

Microservices   

“In short, the microservice architectural style is an approach to developing a single application as a suite of small services, each running in its own process and communicating with lightweight mechanisms, often an HTTP resource API. These services are built around business capabilities and independently deployable by fully automated deployment machinery. There is a bare minimum of centralized management of these services, which may be written in different programming languages and use different data storage technologies.” 

Monolith  

To start explaining the microservice style it’s useful to compare it to the monolithic style: a monolithic application built as a single unit. Enterprise Applications are often built in three main parts: a client-side user interface (consisting of HTML pages and JavaScript running in a browser on the user’s machine) a database (consisting of many tables inserted into a common, and usually relational, database management system), and a server-side application. The server-side application will handle HTTP requests, execute domain logic, retrieve and update data from the database, and select and populate HTML views to be sent to the browser. This server-side application is a monolith – a single logical executable. Any changes to the system involve building and deploying a new version of the server-side application.” 

(See https://martinfowler.com/articles/microservices.html )

Microservice Benefits 

Independent service scalability 

In most systems, the load and throughput characteristics are not uniform. Microservices give you the possibility to scale services independently as needed. When running a monolithic system, there is a structural limitation that requires the entire system to be scaled as a unit. This is an inefficient use of resources. 

Independent development and deployment

Microservice architectures are well suited to continuous integration, continuous deployment, and delivery.  

Small autonomous teams can develop, test, and deploy microservices independently and in parallel. With a monolithic system, more coordination across teams is needed. Releases of a monolithic system, therefore, tend to be larger in scope and done on a slower cadence. Also, as the scale of the deployment is larger, monoliths have a higher chance of creating issues compared to releasing a microservice. 

The improved development and deployment features of microservices enable a faster time to market which can be a critical factor for many systems. 

Changes are easier in a microservice architecture 

Across a system, some services are more prone to change than others. A microservice architecture allows these services to be changed and deployed at their own pace.   

When compared to a monolithic system, each service in a microservice architecture is easier to understand and change.   

When making changes to a monolithic system:  

  • The team must have a deeper understanding of the entire system. 
  • It is more difficult to figure out which parts need updating.
  • It is more difficult to understand the impacts across the system when code in one area requires changes. This increases the chance of introducing breaking changes.  

Another factor in favor of microservices is service boundary stability. Service boundaries in a microservice are easier to keep consistent as they are explicit.

In a monolithic system, the in-process service boundaries are hard to enforce. Overtime these boundaries tend to break down leading to specific functionality being arbitrarily spread across the system. This makes maintenance more difficult and error-prone. As it can be difficult to understand how to correctly implement a change, you can end up in a downward spiral of declining code quality.

Technology Flexibility 

Microservices give you the ability to choose technology based on the specific requirements of each service. For instance, it might make sense to use a document database for one service, a graph database for another and a relational database for another.   

It should be noted, there is a cost to having a more heterogeneous technology stack. As with any design decision, do not make this choice until you have carefully weighed the costs against the benefits. 

Using a monolithic architecture requires a long-term commitment to a particular technology stack. Adopting a microservice architecture allows the internal architecture of each service to evolve independently. If required, a service may be swapped for a new implementation or even removed if it is no longer needed.  

Resilience 

In a microservice architecture, if one service fails, and the failure does not cascade, other services may be able to continue to operate.  

Note that stopping the failure from cascading does not happen intrinsically; the system must be designed to handle failure situations. This includes adopting design patterns such as:  

Microservice Drawbacks 

Complexity 

Microservices are a distributed system. Distributed systems are by their nature, unpredictable. With that comes complexity in developing, testing, operating and understanding the system. Examples of this complexity include:  

  •  When a failure occurs, it can be difficult to find the root cause and understand how other services are affected.  
  •  Transactions that span service boundaries add complexity to the design and operation of the system.  
  •  End-to-end testing is more difficult to setup and execute compared to a monolithic system.

Monitoring and observability strategies need to be factored into the design right from the beginning. Having a robust monitoring strategy is a requirement for microservices.  

Determining Service Boundaries is Difficult  

Deciding on the service boundaries is one of the most important and difficult design decisions in a microservice architecture.

If your services are too fine-grained, you risk having:   

  • Excessive coupling between services. Higher coupling means that a change in one service can potentially affect multiple services, reducing the advantages of “Independent development and deployment” and “Changes are easier in a microservice architecture” described above.    
  •  Performance issues due to network latency. If your services need to use too many other services to fulfill its use case, this can cause an excessive number of network calls, each of which adds latency overhead.  
  •  Cyclical dependencies can cause a so-called distributed stack overflow. This is where a certain transaction is stuck in a loop of two services calling each other.

If you make your service boundaries too wide, that is having your services to coarse-grained, then you lose many of the benefits of microservices such as “Independent service scalability” and “Independent development and deployment.” These were described above in the Benefits section.  

When deciding on service boundaries, you must also consider data consistency requirements. Transactional boundaries should be understood upfront. If transactions need to span multiple services, you need to consider how these transactions will be handled. Some options are compensating transactions, messaging with eventual consistency, the Saga Pattern, or redrawing your service boundaries.  

For information on compensating transactions, see: https://docs.microsoft.com/en-us/azure/architecture/patterns/compensating-transaction 

For information on Saga Pattern, see: https://microservices.io/patterns/data/saga.html

Also, Microsoft has a good article on data considerations for microservices. See: https://docs.microsoft.com/en-us/azure/architecture/microservices/design/data-considerations 

One recognized strategy for determining service boundaries is to use Domain Driven Design (DDD). In DDD, the concept of the Bounded Context is useful for service boundary determination.

For more information on DDD Bounded Contexts, see the article “Identify domain-model boundaries for each microservice”: https://docs.microsoft.com/en-us/dotnet/architecture/microservices/architect-microservice-container-applications/identify-microservice-domain-model-boundaries

Network Overhead 

Even if you get your service boundaries correct, you may still face issues with network latency. This needs to be considered in your design. You should also plan for performance testing and latency monitoring on your production systems.  

Organizational Considerations 

In addition to the technical challenges presented by microservices, organizational structure should be considered. 

One of the main benefits of microservices is “Independent development and deployment” as noted in the Benefits section above. This is centered around small cross-functional teams (5 to 10 people) working independently. These teams should be organized around delivering business value, not around technical capabilities. If your organizational structure and culture do not support these types of teams, you will not realize the full benefits of a microservice architecture.   

You should also consider Conway’s Law which states:  

“Any organization that designs a system (defined broadly) will produce a design whose structure is a copy of the organization’s communication structure.”  

There is evidence, both anecdotal and empirical, that shows organizational structure influences the nature and quality of the systems they provide. 

For more information, see the article “Microservices: Organizational Practices, Part 2” https://dzone.com/articles/microservices-organizational-practices-part-2

Do your teams have the required skills to develop and operate a microservice? 

Microservices are a distributed system. You need to evaluate whether the teams have the skills and experience to be successful in building and operating a distributed system. If not, you may be better off with a modular monolith.   

If you are not familiar with the modular monolith, I suggest you watch Simon Brown’s video presentation available on YouTube at https://www.youtube.com/watch?v=5OjqD-ow8GE 

Conclusion 

While microservices have many compelling benefits, before starting your journey to this architectural style, you need to understand the potential problems. As with any architectural decision, there are trade-offs.  

If your microservices are not designed with enough care and attention, you may end up walking into one of the worst architectures there is, the distributed monolith. This is a system that has all the drawbacks of a distributed system with none of its benefits.  

One potential path towards microservices is first building a well-structured modular monolith. If at a later point you are facing issues that need to be solved using a microservice architecture, you can break out one or two services from the modular monolith and slowly move towards microservices. This also gives you and your teams a chance to incrementally learn what it takes to build and operate a microservice.  

As a final warning about the pitfalls that may lay ahead, I suggest you watch the following videos:

Leave a Reply

Your email address will not be published. Required fields are marked *