For many companies, moving to microservices can mean big benefits for your organization.
As we told you in our blog Going from Monolithic to Microservices, the architecture enables your organization to keep up with frequent deployment, improve productivity, and allows for targeted system changes without impacting the entire application.
However, the complexities of microservices architecture should never be taken lightly. The intricacy, data integration, management, and required skillsets to integrate the new system can be overwhelming for an organization not properly prepared.
To help you out, we have put together a top 7 list of the most common mistakes that companies make when moving to microservices. With these in mind, you can decide if the architecture is right for your application and if so, minimize stress while maximizing ROI.
Currently undergoing a modernization effort? Check out our Platform Modernization blog series and learn everything you need to know about the process, from determining your approach to sunsetting your existing platform.
Most Common Mistakes When Moving to Microservices
1. Assuming Microservices is Always the Next Right Step
The first common mistake organizations make is assuming microservices is one-size-fits-all architecture. While it is a great solution for modernizing some monolith applications, it is not always the right next step and once committed to the architecture, it is very hard to turn back.
Look at it this way, microservices is just another approach to application development. While the architecture is excellent at addressing problems like adapting to rapid changes, scalability, agility, and availability, there are some pitfalls for organizations not properly prepared.
For example, to reap the true benefits of microservices, distributed systems are a must. However, distributed systems increase application complexity. Thus inadequate planning and infrastructure investment could lead to performance issues and increase overhead needed to manage services and ensure they are contained and isolated.
Additionally, microservices comes with a steep learning curve since it requires a different technology stack and team mindset shift. A lot of care must be put into properly managing teams, documentation, and automation testing.
If you are thinking about moving to microservices, it is important to understand both the benefits AND challenges, so you can determine if it is the right next step for your application.
2. Building Services That Are Too Small
Ok, we know what you are thinking, “doesn’t the name MICROservices imply small?”
Yes, you are right. In the end, the architecture is all about building modular services and well-defined interfaces. After all, these services are what give a platform the flexibility to quickly adapt to changes, minimize the impact of these changes, and quickly scale desired services to meet higher demand.
The tricky part is the definition of “modular.” Is it one line of code, several lines of codes that do one thing, or a collection of blocks of code that execute one business logic? This definition is different from person to person and business to business.
Resist the urge to build too small. Going smaller means having more services and each service can have many instances with each instance running within a separate container.
While a container is not as heavy as a virtual machine, there is still considerable overhead in terms of computing and storage to the distributed physical servers in a cluster. As the number of containers increases, so does the stress to the infrastructure and issues in performance. To ensure a certain performance level, companies need to invest in upgrading physical systems that keep up. Inter-communications, scaling, versioning, releasing and rolling updates become much more complicated to automate and maintain. Finally, you must have a good dev-ops and development team with the right expertise to manage the platform.
On the contrary, building too big defeats the purpose of moving to microservices.
So what is the right size for a microservice? Well, the answer to this question varies depending on the business scenario and different mindsets of the people designing the microservices.
Choosing the right size for a microservice is no easy task. However, it is important to consider this critical decision throughout the design stage of your platform and continue to revisit and modify service size as you learn what works throughout this process.
3. Tightly Coupling Services
When moving from a monolith to microservices architecture, there is a tendency to create microservices that are tightly coupled and dependant on one another in terms of inter-connectivity, states, or intentions. In other words, one service cannot function independently without the existence of the other service.
A system of tightly coupled microservices is really the worst of both worlds. You still have a monolith in the sense that modular changes and scaling are difficult. At the same time, you have microservices with unnecessary complexity and high costs.
That said, microservices should be able to function independently. This allows for each service and even each of the service’s instances to be brought offline at any time without bringing down the whole application
It is not always possible to loosely couple all microservices. But at the very least, services that are minor, replaceable, have frequent updates, or need scaling strategies should be independent from the others.
4. Not Centralizing The Logging
To troubleshoot an issue, typically the first step is to look at the logs produced by the application.
In a monolith application, there is usually a central location to look for the logs. However, this is not the case in microservices since a business functionality might consist of several microservices. This issue is amplified when scaled because each of the services has multiple instances and each instance runs and produces logs within a separate container.
Navigating a network of distributed containers in a cluster to locate the necessary logs would be a nightmare.
If centralized logging is not properly planned, designed, invested, and implemented, unnecessary time and money will be spent towards troubleshooting issues.
To avoid this pitfall, all logs should be harvested and routed to one central location where they can be easily filtered and searched and each log can be quickly mapped back to its original request.
5. Keeping States Localized to Microservices
When moving from monolith to microservices, there is a tendency to keep vital states, i.e. cached intermediary calculations, temporary data in files, etc., locally in the services. If done properly, this may work for a monolith but is bad practice for microservices.
Why? Microservices and their instances can go offline anytime due to failures, rolling updates, or by the platform that manages them. Once dead, an instance of a service is gone forever. To replace a dead service, you cannot simply revive it. Instead, new instances will need to be created. This means all of the data stored in the containers of the stateful services will be lost.
Best practice in microservices is to store all states or data in distributed systems (databases, Hazelcast, etc.) where all services and their instances can access necessary information.
6. Not Considering Code Duplications vs. External Dependencies vs. Utility Services
Breaking down a large monolith application into independent microservices introduces a number of code duplications to account for the duplicate logic needed for the microservices to be developed and released independently.
Now, code duplication is not automatically a bad thing for microservices because: (1) it is necessary to have independent services and (2) looking at the service level, there are no such code duplications. See in some cases, services evolve independently causing those original common logics to also change over time.
However, there are common logics that must remain consistent for some microservices. In these cases, code duplication is a problem because one change leads to repeated changes in all of the related microservices.
The quickest solution for this problem is to factor out these common logics into external libraries so that various services can declare them as dependencies. Factoring out code duplication into common libraries helps to eliminate making changes to multiple services and reduces the chance of human error while applying those changes.
But this solution still has a major issue: all corresponding services must be changed, rebuilt and released to get the new versions of the common libraries. This challenge defeats a very important goal of microservices, agility. In some cases, this problem can be resolved by creating utility microservices holding those common logics. Other services will call these utility microservices instead of using libraries. With this approach, agility still holds, BUT we create tightly coupled services.
All of that to say, no single solution is perfect. But we must carefully consider which logics can be duplicated, which should pull from external common libraries, and which should become utility services to help keep the application as agile as possible and the code-base manageable.
7. Not Automating the Versioning and Releasing Process
In a monolith application, versioning and releasing is relatively simple because everything goes together. On the contrary for microservices, some services might undergo rapid changes and require rapid releases, while other services remain relatively static.
In microservices, a service instance is deployed within a container and a container is usually instantiated from an image. This means, different versions of a service usually have corresponding container images’ versions.
Managing a service’s version and its deployments alone should be automated to avoid human error and improve the turn-around time of this process.
More importantly, even if the services are all loosely coupled, their versions’ compatibility must be managed carefully. When microservices mature and have undergone multiple changes and releases, knowing the compatibility of different versions of different services would be impossible without documentation and some form of automation.
Needless to say, microservices is a hot trend in software development and for companies prepared for the move, the benefits are well worth the effort.
However, in order for the effort to be successful, companies need to evaluate existing applications, infrastructure, and other capabilities first and make the educated decision whether or not microservices is the right next move. Your organization should consider if you have the capability to handle microservices in the long run so you can truly reap the benefits of the architecture.
Outsourcing microservices and working with a partner that knows how to conquer the complexities can help you maximize those benefits.
Keep your stress low by contacting KMS and find out how to properly manage this transition, keep the integrity of your data intact, and expand on the skillset of your existing team.