Challenges of Microservices—Are these right choices for you?
By Jaleel Khan
6th May, 2021
Microservices Best Practices
“If you can’t build a well-structured monolith, what makes you think microservices is the answer?” Simon Brown
“Monolith to microservices” is become quite a familiar phrase range from more than 70% of technology leaders today. Nowadays, It appears like everyone is into microservices, and monolith architectures are slowly fading into obscurity. Organizations implement a microservices strategy for designing and detailing an application as a group of loosely coupled services that interact among themselves to deliver a stated business objective.
The Microservices Architecture is a variant of the Service-Oriented Architecture (SOA)—an evolved development approach that has emerged from the world of domain-driven design. Each microservice has a specific function. Yet together they form a complete application, or they perform a global task. Developers can deploy and test each microservice independently. Modern IT workflow consider Microservices as the first step to embrace a DevOps culture that—:
Enables efficient computing
Aids in building resilient applications
Increased business process agility,
Improved scalability and manage multiple things at a time
Faster delivery and deployment to market
An “S” pattern adoption curve validates that there are numerous use cases in which companies benefit from using microservices to develop and deploy applications.
Originally, the technology begins as a great idea due to a need in some pockets, and the solution is developed to satisfy that need. People start considering it as an interesting technology for the future. Then, as its popularity spreads, the technology keeps upgrading on the coolness factor, and the recognition goes beyond the niche use-cases. You may get a clear idea of the concept from the below “coolness factor.”
Conceptually, Microservices prolong the same principles that engineers have exercised for decades. Microservices implementation poses its challenges like most transformational trends. Organizations also notice increased complexity and effort to develop applications with a microservice framework by examining several use cases. In this article, we will discuss some challenges associated with building and deploying microservices including when you should not use microservices. Let’s have a look.
Challenges of Microservices
Organizations face increased complexity when designing microservices compared to monolithic apps. Microservice Architecture is about splitting large, complex systems vertically (based on functional and business requirements) into smaller subsystems that are independently deployable. These sub-systems communicate with each other via a lightweight, language-agnostic network is known as either synchronous (e.g. REST, gRPC) or asynchronous way. If you are using Microservices first, you may face few difficulties such as:
Confusions regarding each microservice’s size and a higher number of Moving parts (Services, Databases, Processes, Containers, Frameworks).
Optimal boundaries and connection points between each microservice
Designing the entire framework to integrate services is harder and time-consuming.
There are multiple design patterns in microservices architecture, but I will discuss Database per Microservice to make the idea crystal clear. If you are interested to know more about the other design patterns, check out Microservices architecture.
The database is the most important decision company faces once it replaces the large monolithic system with many smaller microservices. Many architects prefer having the database as it is, even when they migrate to microservice architecture. It is an anti-pattern, especially in a large-scale system, while it provides some short-term advantage, as the microservices will be tightly coupled in the database layer. A better approach is to provide every Microservice its Datastore, so that there is no strong coupling between services in the database layer. The bespoke design approach will also ensure that the Microservices are correctly segregated according to the Domain-Driven-Design.
But here you may face difficulties Sharing data among services and Giving application-wide ACID transactional guarantee becomes a lot harder. Decomposing the Monolith database to smaller parts needs careful design which is another challenging task. Hence it is recommended to use this design approach while you are working in small-scale applications and one single team can develop all the Microservices.
A bounded context is required for designing microservices requires. Accordingly, every microservice should illuminate, encapsulate, and define a specific responsibility. To apply the same techniques for each responsibility/function, developers usually use a data-centric view when modeling a domain. This is the most challenging approach as, without logic, the data is pointless.
Often Microservices are deployed across multi-cloud environments, that results in high-risk factor and loss of control on the visibility of application components—developers considering these additional vulnerable points. Unfortunately, security testing has not evolved quickly enough to address the risks introduced by this mass adoption of microservices. Vulnerabilities will appear in production if these concerns are not addressed in the SDLC. In addition to this challenge, each microservice communicates with others via various infrastructure layers, which makes testing even harder for these vulnerabilities.
Data security is another paramount concern within the microservices-based framework. Within such a framework data remains distributed. Confidentiality and integrity are correlated. Organization adapts this kind of tricky exercise to maintain the confidentiality, integrity, and privacy of user data.
The monolith application is manageable as you have one single thing to secure. Monolithic architectures are arranged in a single block (sic) and data is usually stored in one storage system. If we break down pillars, well, we can see that the monolith has to handle each pillar.
Now, if we are with a distributed architecture, Where we can consider 3 layers: clients (android, ios, web, …), API Gateways (or Backend for Frontend, BFF), and microservices and their data. There is responsibility segregation through the different layers. Mechanically, microservices are handling integrity, meanwhile exposed layers and front layers are taking care of confidentiality. Accessibility is also shared among all the panels as if they are not accessible, the platform is not functioning.
With microservices, the attack surface increases manifold. You need to take care of all the weaknesses they might expose for each one. Simple security-related bugs or plain old vulnerabilities in supporting libraries or their runtime environment can be the flaws in their design. As a result of this distributed framework, setting up access controls and administering secured authentication to individual services poses a technical challenge as well as increases the attack surface substantially.
The phase of testing is much more complex in microservices-based architecture than any software development lifecycle (SDLC). You must test individual services independently following the standalone nature of each microservice.
When we implemented multiple microservices in larger projects, the focus of the teams must have been on their microservices, resulting in a frequent lack of integration and testing approach. For instance, logging would be performed in a distinct format for complex microservices.
However, The different format was making it difficult to get all the essential information out of the log. Development teams also have to factor in integrating services and their interdependencies in test plans to manage these kinds of complexities.
d. Increased operational complexity:
Once a microservice is built, it needs to be deployed in several testing environments, and later in the production environment. As each microservice team is empowered to decide on its own, which technology to use, how to deploy the service, and where or how to run it, each microservice will most likely be deployed and operated in a different way.
Traditional forms of monitoring are not sufficient for a microservices-based application. Suppose a request from the user interface traverses multiple services before getting to the one that can fulfill its request. The outcome of this traversal is a convoluted path of services, and without the proper monitoring instruments, recognizing the underlying cause of an issue is not only tricky—it’s often impossible.
Scalability — an operational challenge associated with microservices architecture. Successfully scaling your microservice-based applications is challenging, although the scalability of microservices is often touted as an advantage. At the heart of these challenges lies something of a paradox.
To clarify the challenge, here I’m giving an example of two scenarios. When you are operating a single monolithic application from a single server, you can control an increase in demand by allotting more resources to the application. Or else, the individual user making use of an application, running new instances of it, and spread the load evenly in response to high demand.
With microservices, on the other hand, upscaling can involve handling several different components and services. This indicates either all the elements need to upscale at the same time, or you need a means of identifying which individual components to upscale, as well as a method of assuring that they can still integrate with the rest of the system.
Optimizing and scaling require more complex coordination. In a typical microservices framework, an application is broken down into smaller-independent services, hosted, and deployed across separate servers. Another challenge in this architecture is coordinating individual components, particularly when you experience a sudden spike in application usage.
Fault tolerance is needed for every service. Enterprises demand their microservices to be resilient enough to confront internal and external failures. In a microservices-based application, one component failure can affect the entire system. Therefore, the framework you use must follow a design that considers error tolerance for each service that prevents the entire application from failing in the case of individual service downtime.
e. Complexity in communication:
Microservices that are deployed independently act as miniature standalone applications that communicate with each other. Hence, you have to configure infrastructure layers that enable resource sharing across services.
A poor configuration may lead to:
Reduced speed of calls across different services.
In this condition, you’ve received a non-optimized application with a slow response time. All the dependencies that used to be hidden in the monolith, coded in dependency rules between components, now have to be coded in the infrastructure configuration. However, Infrastructure communication is more tricky to maintain, no (not yet) development environment gives you red error indicators when IP addresses or ports mismatch between producer and consumer.
When to avoid Micro services:
Every enterprise moving to a new framework should perform thorough due diligence to ensure it’s the right fit.
These three situations will always help you explore microservices, decide when to skip the architecture for your chosen application.
When your defined domain is unclear or uncertain
Microservices have always been created within a bounded context. Now, think! Sometimes it ecomes logically tricky to break down your business requirements into specific domains as well as it will be equally difficult for you to create adequately sized microservices.
Another challenge of designing a proper means of communication among different services—this complexity is likely too much for you to realize maximum benefits in microservices. Here is the explanation of how an undefined or unclear domain causes difficulties for an organization.
Now, IT organizations embrace a system paradigm across all non-trivial business domains, event-oriented collaboration patterns have become a mainstay of such microsystem architecture design. These pitfalls tend to become a big bottleneck that thwarts event-oriented thinking on the journey toward evolutionary system design. To avoid these pitfalls, IT organizations must ensure that no microservice is designed without an explicit alignment and traceability with the business capability of the domain, as advocated by the bounded context strategy of domain-driven design.
Let’s explain a scenario. Sometimes, clients from the consumer lending domain desire to enable innovation and improve speed-to-market by transforming a single monolithic application into microservices with little or no focus on the design aspect of microservices. The circumstances can cause 500-plus microservices with extreme complexity leading to performance bottlenecks due to chatty inter-service communication.
Considering this kind of challenge, IT specialists always recommended a domain-driven rationalization to address this situation. This not only helps address performance challenges but also ensures the evolution of the application completely autonomously.
Hence, in the coming years, you need to be wiser about your domain design, and if you are not sure it’s wise not to use a micro services-oriented approach.
When improved efficiency isn’t guaranteed
No organization would not prefer to add up complexities and effort to adopt a culture without gaining improved efficiency. The idea of adopting Microservices is to embrace a DevOps culture that in turn:
Employs automation: Microservices enhance agility, which fuels the ability to roll out new service versions. That agility is helpful for shorter build, test, and deploy cycles. Microservices can also
Reduces cost and effort: A fault with a microservice only affects that microservice and its consumers. When monolithic applications experience an error, the entire monolith may break. Hence you may handle maximum work with minimum effort.
Brings operational efficiency: it also incorporates the flexibility needed to employ service-specific security, replication, persistence, and monitoring configurations.
Scalability: Organisations can scale up microservices independently by using pools, clusters, grids. That deployment feature makes microservices an excellent match for the elasticity of the cloud.
Easy to manage: Microservices can leverage the agile methodology, where the application development effort is divided across teams that are smaller and work more independently.
Team strength is another major consideration for applying microservices architecture. For example, consider a relatively small development and operations team maintains the moderately large, moderately complex application. If it’s monolithic, the interactions between individual services may be very direct and may be optimized for specific tasks as required. A small development team is familiar with the code, and maintenance relatively simple for them.
If the same team needs to manage a microservice-based version of the same application, however, their overhead in terms of time and effort may increase significantly. Sometimes the architecture requires more coding time to implement even a minor change in data being handed from one service to another—and small design changes may require changes to the microservice orchestration and management system. It may create strain on the resources of the operations team, as well as the developers.
Hence, first, carry out your due diligence to verify if transitioning to a microservices framework helps achieve these goals.
When your application size is small or uncomplex
When your application size does not justify the need to split it into many smaller components, using a microservices framework may not be ideal. If your applications are already small enough, then there’s no need to break it further.
Remember that the idea of using a microservices framework is to break a complex application into a bunch of different, smaller services. When an application code is not complicated —already small enough and straightforward—transitioning it to a microservice framework will add complexities.
How could you measure Microservices as are the best choice for you?
If the benefits of using microservices outweigh the cons, then of course it is the best choice for you. But you should compare the business benefit with the effort and money you spent to set up the whole infrastructure and apply the approach.
While adopting a Microservice Architecture offers faster delivery and improved efficiency, businesses should deliberate carefully whether to opt for this approach. The benefits of transitioning from a monolithic to the microservices model are a dime a dozen—but there are still challenges to consider.
Here is one of our experiences! We have used Microservices architecture for a FinTech Application system because of its value regarding agility, scalability, and availability. The solution makes clients’ operation five times easy and gets a great response from the end-user level. Hence, for better guidance, you can always reach out to us.