Modernizing a Monolith application
Ever gazed at a towering relic and wonder how it is still standing? Or that it is even balanced?
A few applications I have seen in my career are like so; Monstrous monolithic web applications that take ages to start up and run a full status check. And though it is a thing of beauty in its own hideous way, it is simply a painful experience for everyone involved in its maintenance, whether it be Development, QA or DevOps.
I have heard new grads sigh and wish they could just rewrite the whole damn thing from scratch. I sympathize with them. They are the ones with the enthusiasm, the drive and the audacity to challenge the status quo. And I am sure you and I were one of them not too long ago.
But we see the other side of things now. And for many organizations, this is simply not an option they can take. There is far too much risk involved, especially the possibility that the undertaking itself is most probably an underestimate of the actual task at hand. After all, there are famous tales of despair like Netscape and Windows.
Regardless, the archaic architecture itself should be acknowledged as technical debt, and action be taken to remedy the issue.
Let's start with the basics. An application is usually built like this:
Step 1: Add a layer
An addition of a services framework layer makes the architecture a little more segregated:
Most times, the initial phase will actually mean that the services framework is embedded within the application itself and that is fine for the moment. This step can take a long time and requires an understanding and mapping of the business logic processes. So there is significant refactoring work at this stage.
However, once achieved, this allows the services to be disengaged from the inner workings of the application. Effectively, the services framework provides an API for your application.
Step 2: Replace a sliver of pie
Here is where it starts to get fun. We develop a separate application that has a single function and we replace the appropriate service call in the services framework. The architecture now looks like so:
This implementation has very little risk. The mini application uses the same data store and to the user or the UI layer, the change is transparent. In fact, existing integration tests that start from the services or UI layer will continue as usual, and its results will validate the functionality of the mini application and its integration.
If there is a problem in the implementation, the services layer can re-point back to the original application. This action to rectify the issue can be executed quickly as well.
Step 3: Wash, rinse, repeat
Using the above strategy, we slowly replace the existing services with new mini applications, only promoting them to production when we are confident enough.
The architecture has now evolved to:
In this evolution, the implementation starts to reap enormous rewards:
- Software release and deployment are now based on services instead of an entire web application
- Each service can be separated to the point where it is a single application by itself that can be serviced by its own application container
- A fault in a container does not mean a catastrophic failure of the entire application
- Scaling is more efficient as it is now focused on demand and load of individual services
If this all sounds very familiar, that is because we have now successfully transitioned our dear old monolithic web application to microservices. In just 3 steps!
Before taking the plunge
I have greatly simplified the scenarios and architecture in order to present the concept. Realistically, there are other factors to consider which essentially boil down to complexity.
If you thought Release Management is trickier, that is just the tip of the iceberg. There is also the problem of debugging multi-tier services, tracing performance across service chains and the prerequisite of having a comprehensive understanding/mapping of the main functions that the services should reflect.
Is it worth the endeavour?
Just ask Netflix. And its US$2 billion earnings in just Q2 2016 alone.
There are two ways of constructing a software design. One way is to make it so simple that there are obviously no deficiencies. And the other way is to make it so complicated that there are no obvious deficiencies. - C.A.R. Hoare