on
Monolith to MicroServices: Where do we begin?
Monolith to MicroServices: Where do we begin?
Image attribution — Robert Dimov [CC BY-SA 3.0], via Wikimedia Commons
There is enough literature about how to build MicroServices. However a question I am often asked is where to begin. While some teams start with the core of the Monolith others prefer to start at the periphery. There are teams that start by hacking away at several areas simultaneously. And others who pick away one area at a time. The question is, are we being scientific about it?
This post is an abstract about giving some structure to the thought process about where to begin when moving towards MicroServices. It is based on my experience coaching several teams through the process. The intention is to document my learnings and the possible steps in the achieving our goal.
Step 1: Why and How?
In order to think about “Where to begin?”,
- We need to ask ourselves “Why” are we moving to MicroServices. Hypothesise about “Where” to begin based on the “Why”
- Justify “How” these hypotheses measurably satisfy the “Why?”
The steps in detail.
Why are we moving to MicroServices architecture?
There are usually several answers to this question. Example: Cost effectiveness, long term benefits, industry standard etc. What we are really looking for is that singular problem with the Software that is affecting our Business.
Wait, what has an architectural change got to do with Business problem. The goal is to make it easy for the tech team build software and Business should not see any changes in application behaviour. Maybe not.
It is not the Business’s job to articulate a problem they are facing as an architectural shortcoming. Everything from speed of delivery, stability, agility and mainly customer experience depends on architecture. It is our job to identify and map these problems to our architecture.
Given that architecture itself has to be guided by Business needs, even the strategy for any architectural changes should be tied to Business goals.
Map our “Why” to “Where”
If our intention is to completely move to a MicroServices based architecture, all our code is going to be split up into services anyway. How does it matter where we begin.
Well not in reality. The Monolith is here to stay in form or another, even if we carve our several parts of the application. As we start seeing diminishing returns in terms of benefits for moving the tail end of the system to MicroServices, we are most likely to let those parts stay as is. Not all of us have the luxury to press on when more business critical features require our attention. And by experience I have seen that those new features render old code dead eventually. Given that the Monolith might be around longer than we like, it is better to start with parts that most concern us at this point in time in the context of our “Why”.
Would it not be better to start with the easiest pieces first to build some proof of concept services and then start looking at the bigger pieces?
No, it is very important we begin at the point that is most aligned with the purpose of the move. Proof of concepts have to be treated as experiments. They are never meant produce any production ready code. If there are some technical assumptions that we anticipate might come back to bite us, we should simply set it up as a learning activity and leave it at that. They cannot be our starting points.
To give you some concrete examples, let us consider some “Why”:
- Greater performance and scalability: The starting point for the migration strategy would be to identify the bottleneck that is limiting overall system throughput and start from there. You may want to deploy multiple instances of this piece to improve throughput etc.
- Better maintainability, reduce bugs etc.: You would want to identify that part of the codebase which has the highest complexity, lowest coverage and begin here.
There are plenty of such purposes, each of which requires its own line of thought. For the purpose of explanation I have had to simplify the process. I am quite sure you get the idea.
Justify “How” our hypothesis about “Where” satisfies our “Why”
This question forces us to explain the starting point in terms of tangible metrics. Sometimes even if we have unanimously identified a single starting point, it is beneficial to go through this process.
Please do keep in mind that defining metrics may not be as easy as it sounds. Let us take operational cost savings as an example. The immediate thought that comes to our mind is to look at the overall infrastructure bill. However there are some sunken costs to consider. Any major architectural changes will require significant effort in terms of development effort, temporary spike in defects, drop in velocity etc. Even if we cannot account for every penny in this process it is important to weigh decisions based on hidden costs also.
Step 2: Implementation
With the above step we have answered the “Where to begin?” in terms of which part of the Monolith to attack first. Another “Where to begin?” is about the actual implementation.
I have seen many a teams hurt by simultaneous changes in organisation structure, team structure, tech stack changes etc. Also remember there are other stakeholders who need time to adapt. Example: Product Owners and Managers, Business Owners, etc.
Most of us are aware about Conway’s law and how team structure affects software design. What I have also noticed is that once that Software structure has had some time to settle, teams tend to work within that framework. Re-aligning teams to think in terms of MicroServices requires retraining.
So the “Where to begin?” in terms of implementation has to begin with carving out a team. The idea is to inculcate the discipline of communicating with the carved out piece over Restful APIs, Message Queues etc. However we will continue operating within the Monolith and will not deploy any new infrastructure. For example, we may just have a completely isolated set of tables in the same database. The team has to isolate access to all shared resources and disallow the Monolith from directly reaching into guts of the newly carved out module and vice versa.
The team that is carved out for this step may just be working a single service or a set of services. However the idea is not to freeze this team structure. The intention is for the entire project to learn how to work with the change in architecture and how that changes the communication patterns. Eventually this team may manage a certain business module.
I am leaving out service ownership and team structuring at the project level since that is outside the scope of this post.
When do we know we have completed this step?
- The area carved out by this team has been successfully decoupled and the interactions with the Monolith are completely API based.
- The carved out code has sufficient test coverage. This is absolutely important because when we move to the next step we should be able to conclusively isolate any bugs to deployment problems.
Many a times reaching this stage will already have created several benefits. And it is perfectly okay to take time improving the carved out codebase before deploying it as a service or several services.
Step 3: Deploy to a “Production Like” environment
It is time to test our codebase as an independent deployment. Since the service contracts were already in place, we now have the ability to perform a complete test on a production like environment.
Some aspects to check.
- Component failure, how does the Monolith behave?
- Any additional load on CPU, Memory, Network etc. on the Monolith?
- SLAs for the system as a whole
We can consider this step complete when we have achieved below goals. It goes without saying that the app must work as expected :).
- Deployment automation for the carved out module.
- Feature flagging in the Monolith to call the independent deployment.
Step 4: Go Live
Given the preparation, this step should be relatively easy.
What is important though is the curing time. The curing time is not just for the Service, it is also for the team.
The team has to familiarise itself with keeping multiple deployments alive in the wild. This experience helps them estimate better for other services.
What next?
Back to the drawing board. Start from Step 1.
Yes, it is completely natural to have a different goal in mind now and start from another direction all together at this point in time. The idea is that with every iteration of these 4 steps we should have made a tangible dent in our goals. It is important to keep these iterations small so that our strategy bends and yields to the Business.
The complexity and number of steps may increase many fold as we deploy more services. However the core idea is to treat these activities as controlled experiments. No more than one variable at each step. Too many changes at one go and we may not be able to attribute either success or failure conclusively to strategy, team dynamics or tech decisions.
Originally published on Medium on September 25, 2017.