Way back in August 2008, Netflix had a significant outage because of a major database corruption which prevented them from shipping DVDs to customers for three days. Following this, they decided to move away from a single point of failure–that could only scale vertically–and move to components that could scale horizontally and are highly available [1].

What Is This Article About?

I am excited to share a series of articles on Microservice Architecture Patterns. In this series, we will explore various categories of microservice architecture patterns, including decomposition, integration, database, observability, cross-cutting concern microservice architecture patterns, and others.

In this first article, we will focus on decomposition patterns. These patterns help to break down a monolithic application into smaller, more manageable microservices. In detail, we will discuss three decomposition patterns: microservices decomposition by business capability, microservices decomposition by subdomain, and microservices decomposition by transaction. By the end of this article, you will better understand how to use these patterns to design and implement microservice architecture in your projects.

What Is Microservice Architecture?

Microservices are an architectural and organizational approach to software development where software is composed of small independent services that communicate over well-defined APIs [2]. Basically, microservice architecture approach has become popular in building software systems, especially in modern web applications.

Main Benefits of Microservice Architecture

However, There Are Some Challenges in This Approach

While microservices offer many benefits, they also come with some challenges:

How Can We Overcome These Complex Challenges?

To address these challenges, software developers and architects have developed a variety of software architectural patterns that can help to overcome microservice architecture drawbacks and disadvantages.

Using patterns, you can avoid reinventing the wheel and leverage proven solutions to common problems when designing and building software systems. In the context of microservice architecture, patterns can help address some of the challenges that arise when dealing with many independent services and can reduce complexity, increase reliability, and improve the system's maintainability.

Decomposition Patterns

As mentioned above, there are many different categories of microservice architecture patterns, but without one category of patterns, there would be no microservice architecture. This category is microservices decomposition patterns, which enables splitting the application into a set of loosely coupled services. There are three primary decomposition approaches, and we can learn all of them further. Let's start!

1. Decomposition by Business Capability

Description

This approach is based on business capability decomposition, which aims to create microservices aligned with the business needs and can be developed and maintained independently. Business capabilities are the specific functions or processes that an organization performs to deliver value to its customers [3]. It is a high-level concept that describes what a business does rather than how it does it. For example, a banking application might have business capabilities for account management, transaction processing, and loan origination. Each of these capabilities could be supported by a separate microservice.

This Pattern Is Better to Use If:

Here are some situations in which business capability decomposition may be a good fit:

Advantages

Let's See an Example

Let's consider a hypothetical healthcare platform that provides various services such as patient management, appointment scheduling, electronic medical records (EMR) management, billing and payment processing, and telemedicine services. To decompose these business capabilities into microservices, we can assign one distinct business capability and its data to a separate microservice, which can be developed, deployed, and scaled independently.

Here is an architectural diagram that illustrates this decomposition.

In Picture 1, we can see how the healthcare platform can be decomposed into microservices based on business capabilities:

We can achieve better scalability, flexibility, and maintainability by decomposing the healthcare platform into microservices based on business capabilities. For example, we can scale up the Telemedicine microservice during a pandemic or other situations where remote consultations are in high demand without affecting the performance of other services.

Possible Challenges and Issues

  • Difficulty in identifying business capabilities: Identifying and defining the appropriate business capabilities to use as the basis for microservices with the proper boundaries can be a complex and time-consuming process.
  • Tight coupling between microservices: If business capabilities are not clearly defined or there is an overlap, there may be a high degree of coupling between microservices. A high degree of microservices coupling can make modifying or replacing individual ones difficult without affecting the overall system, increasing the risk of downtime or other issues.
  • Complexity in coordinating microservices: Coordinating the various microservices involved in a business capability can be complex, especially if the business capability involves multiple steps or interactions with external systems.

2. Decomposition by Transaction

Description

One popular approach to decomposing microservices is through transaction decomposition, where the system is designed such that each particular transaction belongs to a separate microservice. A transaction, in this context, refers to a series of operations performed between components of the system as a unit of work to achieve a particular business goal.

In this pattern, the components that participate in a transaction are grouped together as part of the same microservice. This grouping helps to avoid problems with two-phase commit and reduces latency issues that may arise in a distributed system. By adopting this approach, organizations can achieve a more efficient and scalable microservice architecture that is better suited to their specific business needs [6].

This Pattern Is Better to Use If:

This pattern can be reasonable in the following scenarios:

Advantages

Let’s See An Example

Let's consider an e-commerce application that allows customers to purchase products online. To implement this application using microservice architecture, we could use the transaction decomposition pattern to break down the system into smaller, more manageable microservices that each handle a particular transaction.

Here is an architectural diagram that illustrates this decomposition.

In Picture 2, we can see how the e-commerce platform can be decomposed by transaction into microservices that could be part of this system:

By breaking down the system into these smaller microservices, we can achieve a more scalable, fault-tolerant, and efficient system that can better handle the demands of a high-traffic e-commerce website. Each microservice is responsible for a specific transaction, which helps to minimize complexity and improve performance.

Possible Challenges and Issues

  • Potential for monolith creation: When using the transaction decomposition pattern, it's possible to package multiple modules together into a single microservice. It, in turn, can create a monolithic architecture, which goes against the principles of microservices. To avoid this, it's important to keep each microservice focused on a single business domain [7].
  • Increased cost and complexity: If a single microservice handles multiple functionalities instead of separating them into separate microservices, the cost and complexity of that microservice can increase. It, in turn, can lead to longer development times and higher operational costs. It's essential to carefully consider the scope of each microservice to avoid this.
  • Incompatible versions: When deploying microservices, it's possible to accidentally deploy different versions of the same microservice for the same business domain. It, in turn, can lead to inconsistent behavior and potential errors in the system. To avoid this, it's important to carefully manage versioning and deployment processes.

3. Decomposition by Subdomain

Description

Microservice decomposition by subdomain is a process of breaking down a monolithic system into smaller, independent microservices based on the corresponding subdomains defined by Domain-Driven Design (DDD). DDD refers to the application's problem space - the business - as the domain, which is comprised of multiple subdomains [8]. The scope of each subdomain's model is called a bounded context, around which microservices are developed. This pattern is suitable for monolithic systems that have clear boundaries between subdomains and allows the repackaging of existing modules as microservices without extensive code rewriting. By breaking down the monolithic system into microservices based on subdomains, each microservice has its own model, which enables greater agility, scalability, and maintainability.

This Pattern Is Better to Use If:

Microservices decomposition by subdomain is a software design pattern that is well-suited for applications that have complex business logic and are expected to evolve over time. This approach to software design enables developers to break down a large, monolithic application into smaller, independent services that are focused on specific areas of business functionality.

Here are some scenarios where this pattern is well-suited:

Advantages

Let’s See An Example

Let's consider an insurance monolith application that allows clients to purchase insurance online. To implement this application using microservice architecture, we could use the subdomain decomposition pattern to break down the system into smaller, more manageable microservices that each belong to a particular subdomain. Here is an architectural diagram that illustrates this decomposition [10].

In Picture 3, we can see how the insurance monolith application was decomposed by business capabilities into four services: sales, customer, compliance, and marketing. Then the sales service was further divided into purchasing and claims subdomains, while the marketing subdomain was divided into campaigns, analytics, and reports subdomains.

Here's a brief overview of microservices that were created in each subdomain:

By decomposing this monolith into microservices based on subdomains, the company was able to improve its agility, scalability, and time to market. They could independently develop, test, and deploy each microservice, allowing them to innovate faster and respond quickly to changing market demands. Additionally, they improved the reliability and availability of their services, as failures in one microservice did not affect the entire system.

Possible Challenges and Issues

  • Potential for creating excessive microservices: This pattern can result in the creation of a large number of microservices, which can make service discovery (the process of finding and connecting to available services) and integration (combining these services to form a functional system) challenging. As a result, it leads to increased complexity and potential operational issues.
  • Difficult to identify business subdomains: This pattern requires a thorough understanding of the overall business to determine the appropriate subdomains. Without sufficient knowledge of the business, it can be challenging to identify the most appropriate subdomains, potentially resulting in suboptimal microservice design and implementation.

Conclusion

In conclusion, microservice architecture is a powerful approach to building modern distributed systems, and decomposition patterns provide valuable strategies for breaking down a monolithic application into smaller, more manageable microservices. By using patterns such as decomposition by transaction, decomposition by subdomain, or decomposition by business capability, teams can create a more flexible, scalable, and maintainable architecture. However, it is important to note that each pattern has its advantages and disadvantages, and choosing the wrong strategy can lead to significant challenges and issues. Therefore, readers should carefully consider the specifics of their project and choose the correct pattern that best suits their needs to ensure a successful implementation of microservices.

About the author

Zufar Sunagatov is an experienced senior software engineer passionate about designing modern software systems. He strongly advocates microservice architecture and has worked extensively with complex distributed systems using various design patterns in big e-commerce, fintech, and insurance companies. Zufar is an active member of the software development community and regularly shares his knowledge and expertise on his Telegram channel ZufarExplainedIT and LinkedIn where he explains algorithm and system design task solutions and approaches that have been well-received by the community.

References

  1. https://networknuts.net/netflix-aws-case-study/
  2. https://en.wikipedia.org/wiki/Microservices
  3. https://learning.oreilly.com/library/view/microservices-patterns
  4. https://docs.aws.amazon.com/prescriptive-guidance/latest/modernization-decomposing-monoliths/decompose-business-capability.html
  5. https://microservices.io/patterns/decomposition/decompose-by-business-capability.html
  6. https://www.youtube.com/watch?v=IHhM6OmUoFI
  7. https://docs.aws.amazon.com/prescriptive-guidance/latest/modernization-decomposing-monoliths/decompose-transactions.html
  8. https://microservices.io/patterns/decomposition/decompose-by-subdomain.html
  9. https://www.tutorialspoint.com/microservices_design_patterns/microservices_design_patterns_decompose_by_subdomain.htm
  10. https://docs.aws.amazon.com/prescriptive-guidance/latest/modernization-decomposing-monoliths/decompose-subdomain.html