Comparing monolith with microservices
A microservices architecture is a series of services that communicate with one another to achieve complete application functionality. Each microservice has a similar pattern to a monolithic architecture but only covers one function within the entire application functionality.
This means that each service can have a data access layer that is customized to use several kinds of database technologies and a business layer that is customized to use wide varieties of technology to perform the functional aspects of the microservice. To elaborate on the business layer using our case study detailed in future chapters, this means that instead of having all the OAS back-end code in a single layer, we have individual services for setting up an auction or placing a bid.
The microservices architecture iterates on previous models with more communication and an all-encompassing front-end functionality. All the back-end services now communicate with each other to represent actions that users can experience through a single point of entry within the front-end, as illustrated in Figure 1-3.
FIGURE 1-3 Microservices architecture
SOA versus microservices
You might also wonder how SOA differs from microservices. Microservices are fine-grained services where each service is modeled for a business domain or capability. SOA services are usually coarse-grained services that are not completely decomposed based on the business domain. Microservices are more abstracted and segmented by the individual business functionality. We will cover this in detail in future chapters, but the use of domain-driven design is a major design factor in microservices that is distinct from other architectures. Domain-driven design specifically aligns services to individual business functions in an application.
Also, microservices have more complex patterns when it comes to communication and messaging. Where we once had an enterprise bus as one of the innovative features of an SOA, we now have a broader set of technologies and mechanisms, such as request-response and publish-subscribe communications. These patterns will help distribute communication channels for better performance in an application, rather than making the service bus the bottleneck of the system.
Another advantage of microservices is rooted in using lightweight protocols, such as HTTP, whereas with SOA, we use other protocols such as TCP or MSMQ. There are many examples in which microservices are the presumptive choice for your application architectures. To help illustrate this better, we will dive deeper into some of the issues with legacy architectures.
Now that we have talked about the high-level differences, let’s run through an exercise to understand the minute differentiations between monolithic and microservices architectures. To help illustrate this, see Figure 1-4, which illustrates how the monolithic architecture requires a full application deployed in each host, making it difficult to scale.
FIGURE 1-4 The monolithic architecture is difficult to scale
Figure 1-4 helps clarify the nuances of a monolithic application. Here, we have a collection of services that are ultimately deployed on two virtual machines (VMs)—all containing the same services within each host. As you can see, the scaling solution in place essentially deploys the full application on multiple VMs.
Now let’s compare the monolithic architecture with a microservices approach. Figure 1-5 illustrates how the microservices architecture can be deployed independently in several different hosts and is more capable of scaling.
FIGURE 1-5 Microservices architecture
Figure 1-5 shows how microservices architecture differs from the monolithic approach. Virtual machines can be deployed in the microservices architecture, but instead of deploying all components of the application in a single VM, we see that each service is deployed independently on several VMs. Furthermore, with a monolithic application, any deployment that might have issues or bugs would have to be rolled back and analyzed carefully for mistakes. Not only is this tedious, but it provides a bad user experience for your app’s consumers because of bugs and unexpected downtime. This allows us to scale based on functional need, doesn’t result in overexpenditure of your resources, and enables a more fine-grained control of your services. If you experience deployment issues, you can easily find errors and redeploy with flexibility and velocity.
To understand how microservices promote scalability, suppose we are running an order management system in which users can place orders. On weekends, the system load is increased by a high number of user orders, which causes response timeouts and improper handling of resources. With the appropriate monitoring framework in place, we can identify when the order service is not handling a larger amount of requests. Based on this, we can just scale out the order service, rather than scaling out the whole system. This allows us to save our resources inexpensively.
Databases in a monolithic architecture
Let’s focus more on the data tier of the architecture. Figure 1-6 shows that a monolithic database might not be a good design choice when it is shared across many services.
FIGURE 1-6 Monolithic database when shared across many APIs
As you can see, the data access layer in Figure 1-6 utilizes a single monolithic database that is shared across multiple services. This database also tends to be a relational database to store information, and all the app services that are operating in the middle tier perform actions directly on this single data tier.
If your application continues to grow, you might start noting issues with the scaling of your database and with maintaining this data. All the different services are recording particular information relevant to their service’s operations, and it becomes very difficult to segregate this within your database.
Databases in microservices architecture
The microservices perspective is shown in Figure 1-7.
FIGURE 1-7 The microservices architecture
In microservices, you design with the domain or business functionality in mind. This means that you can segregate the services by business functionality, so each service can have its own particular database. Furthermore, you can specifically pick the technology behind the database of your choosing based on the need of the service. This provides even more customization, and it is a great benefit to leverage. Granted, when we abstract these services even more, we face difficulties with database consistency. Thankfully, as we mentioned earlier, there are many patterns in place to address that concern, which shows how microservices can truly make a difference in your application architecture.
When discussing the architectural features of microservices, we should also be aware of new movements and trends that continue to positively affect this paradigm, such as micro front-ends.
A micro front-end is similar to having various back-end microservices because the front-end is segmented along the same verticals. In the future, we will see more micro front-ends as we continue to evolve software architecture (see Figure 1-8).
FIGURE 1-8 Microservices architecture versus micro front-end architecture
Figure 1-8 shows the current evolution of microservices architecture. When it comes to micro front-ends, we see that the front-end is further abstracted and connected to the back-end microservices over the same API gateway. This means that the UI/UX components of each of the services are segmented to those applications only. Then, all these separate components are placed together in a container app that serves as a placeholder for these HTML components with embedded data. When deployed, the components are rendered into a single front-end that is seen when the user accesses the overall application, say, through a web browser (assuming it was a web app). In traditional microservices, data components are received as JSON payloads, but in micro front-ends, data components are received as HTML components.
This componentization has similar benefits to those discussed in the next section, but this example helps illustrate its usefulness.
Let’s take three teams—named Service 1, Service 2, and Service 3—operating in distinct service verticals. This means the Service 1 team can build and deploy the Service 1 full stack microservice, meaning they can build and deploy its respective data layer, business layer, and front-end. Likewise, the Service 2 and Service 3 teams can do the same, without any dependency on the other verticals.
Many of the benefits and challenges of micro front-end are strongly correlated to their respective back-end microservices. We will cover this in more detail in the next section. In this book, we use the OAS as a way to illustrate many of these concepts in practice, though we did not use this particular feature in our case study. We still want you to be aware of micro front-ends because you will likely see their underlying patterns time and time again. Different layers and components of application architecture will always be further abstracted in order to create simplified, yet richer, scenarios for developers, engineers, and more. This is something that will always grow in popularity, and is a trend to observe and track as we continue evolving our application design strategies.