Sitemap
iyzico.engineering

The engineering behind iyzico, the sweet home for iyzicoders…

Microservices: Divide and conquer, but it costs

12 min readMay 15, 2025

--

Hello everyone! In this article; we will examine the popular method Microservice architecture, contrary to the general, from the empty part of the glass and talk about its disadvantages. While doing this, it is better to proceed conceptually rather than technically; not examples from any technology, framework or language, but with logical inferences.

Press enter or click to view image in full size
Photo by Growtika on Unsplash

Of course, each project should have the architecture that best suits it and should be developed accordingly. However, sometimes due to factors such as popularity, misunderstandings/incorrect approaches, team knowledge levels, and similar reasons, incorrect architectural choices or poor/incomplete implementations are made. To avoid this, in order to select the most appropriate architectural approach, it is important to not only consider the advantages it provides but also to be aware of its disadvantages. Therefore, the relevant approaches should be thoroughly understood, with both their pros and cons, and the right decision should be to choose the one that best suits the project’s functionality.

In our review, we will discuss various disadvantages/challenges related to the Microservice architecture to raise awareness about these issues. We will categorize these disadvantages according to the project’s lifecycle stages:

  • Planning: Challenges encountered during project planning
  • Implementation: Challenges that may arise during the project implementation
  • Maintaining: Challenges related to maintenance and management after the project is completed

The Microservice architecture generally defines how distributed systems can work together correctly and efficiently within a set of rules. Therefore, most of the disadvantages we will address in this review will parallel the issues typically found in distributed systems.

A Brief History

To better understand the events and establish a correct cause-and-effect relationship, it would be appropriate to provide a brief historical introduction.

The first concepts began to emerge in the early 2000s, influenced by Service-Oriented Architecture (SOA). With the widespread use of the web, the need for efficient resource utilization required projects to be more modular and scalable. The standardization of various web protocols (such as WSDL, SOAP, REST) made it possible for different systems to work together.

By the 2010s, these concepts had merged, and new ideas began to emerge. According to these concepts, a software project could now be defined in a distributed, modular, and flexible way. With the advancement of virtualization and cloud technologies, Microservices completed its evolution and became a standard.

Today, many projects with a Microservice architecture exist, and new ones are being developed.

Planning

We have a project in mind and we want to carry it out, but we’re unsure where to start and how to approach it. This confusion can certainly be resolved with a well-structured plan, and typically, there is a planning phase when starting a project (and there should be). This phase is critical because it determines the project’s rulebook. The rules we set during this phase define the project’s capabilities and its general working principles.

Capabilities refer to the functions that the user expects from the project, such as listing products, creating a cart, placing an order, etc. However, there are also tasks that need to be done for these functions to work properly, meaning the system needs to be able to operate efficiently. These can be referred to as the working principles.

Knowledge & Extra Definitions

In a Microservice architecture, each function is achieved through the coordinated operation of different systems grouped within themselves. The correct definition of these distributed systems is critical because of the advantages they offer. Incorrect or poor definitions here will directly affect the benefits of the Microservice architecture, and as a result, our expectations will not be met.

This is where the first challenge arises: incorrect definitions directly impact the outcome, and in this sense, the Microservice architecture has very strict rules. Therefore, right from the start, in the planning phase, there is a need for extra knowledge and expertise. Even before the functions are defined, there are many issues that need to be determined:

  • How will the systems communicate with each other? How will latency be managed?
  • How will data consistency between systems be ensured?
  • How will a problem or fault in one system affect the others, and to what extent?
  • How will scaling be done and managed? How will the load be distributed?
  • How will security between systems be ensured?
  • …

Without finding answers to these and similar questions and making clear definitions, we cannot fully implement a Microservice architecture. Therefore, the way the system will operate is just as important as the project’s capabilities, and it requires additional knowledge, extending the planning phase. In the end, you may find yourself in meetings where the project capabilities are never discussed, but the focus is on how those capabilities can be achieved.

Topological Complexity

In a Microservice architecture, you implement your project by breaking it down into “mini-projects”: instead of a single project that provides all the functions, you have sub-projects that provide grouped functionalities.

For example, if you’re planning five microservices, it’s great that each of them can work independently. However, in this case, the number of systems you need to think about and design will increase by the number of services you have. Instead of solving the problems of a single system (monolith), you’ll have to solve the problems of multiple systems. This means five different security systems, five different scaling solutions, five different monitoring setups, etc. Each independent subsystem (service) will add complexity to the overall architecture and make management more difficult.

Data Consistency

We’ve discussed the independence of each system in a Microservice architecture. In this case, each system should have its own data and define its own space (database) for those data. But what about shared data?

Let’s consider an e-commerce system as an example: One service is providing product details, another service is handling stock tracking, and another one is managing orders. We wouldn’t want to sell products that are out of stock. To prevent faulty orders and provide a better user experience, these services must work in a consistent manner. This means we need to ensure that shared data across these services stays up to date.

It’s not just about shared data; we also need to maintain consistency for interrelated data. A function might trigger sequential operations across different services, and the results of these operations may affect each other. In this case, to maintain overall consistency, services must update their data according to the results of other services.

Beyond these, there are scenarios where we must manage data consistency, such as:

  • Different data types and transformations: Shared data might be defined as an enum in one service but as a numeric value in another, or entirely different database technologies might be used.
  • Concurrent requests: There could be user requests that fall to different instances of the same service at the same time, or multiple requests trying to work with the same data.
  • Replication: A service’s database could be replicated across multiple instances, and in this case, each database must stay in sync and be kept up to date.

These are some of the complexities of managing data consistency in a Microservice architecture, and addressing them is crucial to ensuring the system functions as expected.

Communication and Networking

In a Microservice architecture, communication between services is crucial for the system to function properly. However, since each communication happens between distributed systems, it incurs a cost (latency). Even if everything runs smoothly, there is a network cost due to each service being hosted on different servers. If we consider negative scenarios (such as slow services, network issues, etc.), this cost can increase significantly. Therefore, having a proper network configuration and ensuring that the workflows perform efficiently are of great importance.

Another challenge arises from the freedom of using different technologies for each service. In such cases, services may communicate using different protocols. This prevents the establishment of a common standard for service-to-service communication and introduces an additional problem. Even when the same protocols are used, data transformations (serialize/deserialize) still create extra costs.

In summary, managing network latency, ensuring compatibility between diverse technologies and protocols, and optimizing communication between services are key factors in minimizing these costs and ensuring the system operates effectively.

Fault Tolerance

There may be scenarios where multiple services need to work in sequence or concurrently to perform a function. In such cases, any physical or logical issue that occurs in one service must be known by the other services, and action plans should be created accordingly.

The severity of these action plans can vary depending on the criticality of the function. For example, after a problem in one service that can affect the entire process, other services may need to immediately stop their operations and roll back any actions performed up until that point. In less critical functions, the required action might not be as drastic or strict, and the resolution can be deferred to a later stage of the process.

Preparing action plans for such scenario-based situations will also extend the planning phase, as it requires anticipating various failure points and determining how the system should react under different conditions.

Implementation

After defining all the capabilities of the project and the general working principles of the system in our planning, we can now move on to the implementation phase.

Get Volkan Akkaya’s stories in your inbox

Join Medium for free to get updates from this writer.

The subtopics we’ll explore under this heading are the challenges we might encounter while coding the project.

Extra Mechanisms

“The tasks that need to be done for the application to correctly perform the actions we want.”

This sentence is a great summary of the primary challenge we will explore under this heading. The definitions made during the planning phase to ensure the system operates smoothly often lead to the creation of additional structures, and writing these structures extends the application process.

For example, a structure that balances and distributes incoming loads, a system to manage communication between services, or a structure that will handle scaling. The list can continue depending on the scope of the project and negatively affect the implementation phase.

Dependency Hell

The Microservice architecture minimizes business logic dependencies by creating independent services, but it also introduces additional technical dependencies due to the structures we discussed in the previous section, which are necessary for the system to function. Since each service has its own world, each may have its own set of dependencies, and if these dependencies are not managed properly, it can lead to a complex web of interdependencies.

For example, one service might be using a specific version of a library for communication, while another service might be using a different version of the same library. Even if it’s just one library, remember that this library may have its own set of dependencies. Now consider the set of dependencies created by different versions of libraries, including potential conflicts between those versions.

Even though these dependencies can be managed with different solutions, the risk of dependency conflicts will always exist due to the principle of independent operation in Microservices. This challenge must be carefully handled to avoid potential issues related to versioning and dependency mismatches.

Limited Reuse of Code

The Microservice architecture is limited in terms of code reusability. Due to the principle of services operating independently, their dependencies need to be minimized. This, in turn, limits the use of common functions defined in shared libraries across services.

Of course, this limitation can be stretched to some extent, and shared libraries can be created. However, this compromises the independence of the services. Finding the right balance between sharing code and maintaining service independence directly impacts software development costs and timelines.

Thus, while reusability and shared functionality can improve efficiency, they must be carefully managed to avoid undermining the core principles of Microservices.

Hard to Standardize

Another challenge that arises due to the independent operation of services is code standardization.

Each service creates its own “world” with its functions, structures, and configurations. While this world may have its own internal standards, there are likely to be differences when compared to other “worlds” (services). These differences often arise because services are developed by different teams. Similar code structures can be written with different designs, libraries, or approaches. As a result, it becomes challenging to enforce a common standard across the project in terms of code.

Moreover, services may be written in different technologies, which might make it impossible to write identical structures across services. The communication between services built in different technologies may also vary, creating additional complications in defining and enforcing common standards.

In summary, maintaining code standardization across services is more difficult in a Microservice architecture, particularly when different teams and technologies are involved, and this adds complexity to project consistency and collaboration.

Testing & Debugging

We mentioned earlier that applications in a Microservice architecture, being defined across different servers or locations, create a complex ecosystem. This complexity directly affects testing and debugging processes.

When you want to test an existing workflow or a newly defined one, depending on the scope, you need access to either part of or the entire ecosystem. This makes testing more challenging.

Similarly, when trying to debug an application, you encounter a similar problem. To examine an ongoing workflow between services, you may need the source code for all the services involved in that workflow and need to set up environments where these services can operate.

Additionally, test environments created for Microservices projects are likely to become cluttered over time due to shared usage by different teams. To avoid this, local test environments can be set up. However, for large projects, this can lead to high resource consumption and may not be feasible.

These complexities emphasize the need for careful planning and management of testing environments to maintain efficiency, especially in larger Microservice-based projects.

Maintaining

Having made it this far, it means we’ve overcome all the challenges of the Microservice architecture and managed its disadvantages effectively — congratulations! From here on, the next step is to manage this distributed system efficiently. However, of course, there are still some challenges we might encounter in this phase, and in this section, we’ll discuss those as well.

Efficient management of a distributed system, especially one based on Microservices, requires continuous monitoring, scaling, and ensuring that all services remain properly integrated and aligned with the overall architecture. It’s essential to anticipate and address these potential issues to maintain a smooth operation.

Complex Logging & Monitoring

Logging is a crucial concept for tracking workflows. Each service, because of working independently, generate independent logs. However, this often has a negative impact when it comes to tracking workflows that span across multiple services. For proper process tracking, the logs of relevant services need to be gathered and organized.

Additionally, since services can work concurrently and with multiple instances, simply using date information for log tracking often isn’t sufficient. Therefore, there is a need for an additional distinctive field for workflow tracking.

Monitoring is real-time tracking of the overall health of a running and serving system. This allows for quick identification of problems that may occur within the system. However, due to the inherently complex ecosystem of Microservice architecture, monitoring becomes more challenging. While the status of each individual service can be easily monitored, to track the overall system health, the metrics of each service need to be collected, combined, and reported. This adds complexity to the overall system monitoring and makes it harder to get a clear view of the entire ecosystem’s status.

In essence, both logging and monitoring require careful structuring and tools that can aggregate and analyze data across multiple services to ensure seamless tracking and management of the distributed system.

Deployment Challenges

For an application built with Microservice architecture to function properly, all services must work in coordination. Therefore, it is essential to accurately identify service requirements and configure the working environments accordingly.

The setup of each service in different environments, along with the preparation of infrastructure that ensures communication between these environments, requires numerous actions such as defining and implementing security procedures, configuring the environments according to disaster recovery scenarios, and managing scaling strategies etc.

In short, since Microservice architecture splits the application across different environments, it also brings the responsibility of managing these environments. Proper coordination and management of these various environments are crucial for ensuring the seamless operation of the system.

Costs

In Microservice architecture, instead of a single large system, you write smaller systems divided into meaningful parts. However, this division may not always be linear in terms of costs. Here’s how we can explain this:

For example, let’s say a monolithic application that requires 10 units of resources is being converted into a Microservice architecture with 5 equal-weight services. As we’ve mentioned, each service is an independent system, and these systems come with additional costs. This must be factored into the calculation. If each service, which we expected to require 2 units of resources, ends up needing 3 units (due to the its own overhead), we might be looking at a total resource demand of 15 units instead of the original 10.

The resource requirements mentioned here encompass all aspects needed for the project: planning time, personnel, or physical hardware. The costs can be monetary, time-related, or mental :)

It’s worth repeating: each service is an independent system, and systems come with their costs.

Adding New Services

Applications evolve over time to meet changing needs, and in such cases, additions or removals may be required.

However, in Microservice architecture, every new service added will come with its own set of requirements and will further complicate an already complex ecosystem. It will also increase management costs. Therefore, any new service to be added should be thoroughly analyzed and go through all the processes we’ve previously discussed. This, in turn, will negatively impact its development costs.

Conclusion

In this article, we examined the challenges and some disadvantages of Microservice architecture by breaking them down into different stages as subtopics.

While we focused solely on the negative aspects, which may have been intimidating, it’s important to note that these challenges are obstacles we must overcome to take full advantage of the benefits offered by Microservices. Projects developed with this architecture, when handled with good planning and by a skilled team, can result in high-quality software with many advantages. In fact, this article also highlights what to focus on in order to effectively leverage those advantages.

Microservice architecture is an expensive choice with high promises, so this choice should be made consciously.

--

--

Published in iyzico.engineering

The engineering behind iyzico, the sweet home for iyzicoders…