Should You Move Your Monolith to Microservices?
Sometimes, breaking the monolith into microservices is not a good idea. Here’s why, and how to make the right choice
The monolith, with all its strength and power, is a pillar of your company’s technical prowess. Why would you want to break it apart into measly microservices? Well, we know the answer why, but the path is still a mystery to most. Many organizations are stuck in application infrastructure analysis paralysis as they consider moving from monolith to microservices in a monolithic way. Doing so is counter to DevOps and here is why.
Today, deconstructing monolithic applications into microservice-based applications involves a lot of heavy lifting, including:
- Identify discrete application components and services.
- Building up and adopting container-based and K8 infrastructure.
- Adjusting frameworks, backends, and configurations to also support a services-based architecture.
- Refactoring code to support services such as building APIs and being more event-driven.
It sounds—and often is—an overwhelming task. The reality is not all monoliths need to be decomposed. Many applications, especially mainframe-based ones, will do just fine serving their value as is. And today a lot of great technologies such as Zowe make it easy to make modern interfaces to mainframe applications. But there is more likely than not a case from going from a monolithic application to a services-based one beyond the ability to deliver functionality; it could be better organizational structure for your engineering team, lower cost or greater visibility.
Often when I have conversations about what to do with their monolith, their solution sounds very waterfall. Organizations make a big assumption that they should move their monolithic application to microservices in a very project-based way. The problems with this are all the same problems that come with waterfall projects, but they are compounded by several things:
- This is a six-month-plus project. By the time your done application initiatives will have already adapted even more. So instead of microservices, you will want serverless, for example.
- It will dramatically delay any new functionality. Product planning meetings will constantly be filled with the phrase, “We probably should just wait on this feature until we decompose the monolith.” You will have to create a whole team around it, and you won’t be delivering to your users.
- The benefits may not be what you expected. Let’s say it’s only six months—you get done and then what? Has the decomposition really given you any gains or are you just in a better position to deliver now delayed functionality?
- You will awake the graveyard. Before the move, your technical debt can be nascent and not impact application quality or performance. But a decomposition will undoubtedly awaken the beast and surface dangerous technical debt you did not expect.
- Application components are likely to change. As you try to isolate discrete components in your monolith you will find that they do not directly align with services in the anticipated modern version of the application.
Expecting the unexpected and preparing for the worse is a given. I would suggest that moving your monolith to microservices monolithically is a bad idea. But I can see how we got there. In the early days of containers, there was a big push to containerize everything, no matter how big it was. In addition, there was a false sense that to be DevOps, a company had to make the move to microservices. However, DevOps methodology has nothing to do with the outcome, and everything to do with how you get there in the most efficient and effective way. So even with a mainframe environment, your application development can be driven with a DevOps mindset.
The best approach to moving your monolith is in pieces. There are several aspects to this:
- Build a services layer to the monolith. The strangler design pattern, for example, is built just for this. The service layer acts as a facade from the user’s perspective, where everything looks like it’s coming from the same architecture. This service layer can be built with minimal disruption to the application and development processes, as ideally you have a separate team build the services layer and facilitate the interaction.
- De-bloat. After the services layer is up and running, de-bloat the monolith in a very functional way. Build new services on the modern version of the application and when the parity is complete, turn off that aspect of the services layer and switch to the new microservice.
- Avoid like-for-like code changes. When you identify services to decompose, do not do a copy+paste of the code or even refactor. Rewrite the application from the feature down. What you are replicating is functionality, not code. This is very important because now is the time to wipe away the hidden technical debt and leverage modern development practices. This will help with the whole delivery chain supporting modern quality, testing and release automation.
There is a lot of burden put on the services layer, but that layer will be hugely beneficial: When it comes time to reconsider your microservices, as this is likely to happen, you already have that abstraction to help.
You may never get rid of the monolith, and oftentimes the straggler is some aspect of your backend. It’s hard to lose complexity there. One of the remaining challenges of taking the gradual approach is being comfortable with two separate organizational structures and maintaining two disparate environments. But the reality is, even in the project-based approach you are doing this for at least six months and in a far more contentious way.
Modernizing the monolith through microservices oftentimes is a people and talent challenge, and this is a challenge I do not have a good answer for. The organization not only needs to understand the technical aspects but also what it means to build a modern development team. There is a chance that the team organized to build a modern version of the application maintains the monolith mindset. When this happens the outcome is that the modern application is just an upgraded version of an old bad habit, not a new approach to delivering the same functionality.
The benefits of moving from monolithic architectures and development practices to microservices/container-based architectures and DevOps practices are tremendous and seldom do I hear arguments against it. But take the pressure off and don’t force the organization to do it in a project-based way.