Breaking the Monolith
A monolithic codebase is a very well-recognized problem many production systems that are existing for a long time are facing today.
Join the DZone community and get the full member experience.
Join For FreeA monolithic codebase is a very well-recognized problem many production systems that are existing for a long time are facing today. Re-architecting it with a completely new system comprising of domain-isolated microservices implemented from scratch is very rarely possible. Primarily because it's impractical to the business folks to shut down the existing system which ultimately has to fund this exercise and also because of the risks of failure associated with such a big-bang cutover.
Most often, we as developers would have to do it by breaking down smaller subsets of related functionality into microservices, one after the other, while keeping the overall application running and available to the business. Having done this exercise more than once, I intend to capture some of my learnings with this article.
Identify Sub-Domain Boundaries
The first task is to identify one set of related functionalities that can be modeled as a single self-contained domain. This doesn’t have to necessarily translate into a single microservice always, but the key is to note that this sub-system has to be deployable, maintainable and scalable on its independent of its consumers.
Identify Asynchronously Executable Functionality
When isolating a specific functionality, not all of them would have to be executed on the server while keeping the caller waiting for a response. This is a key pattern that has helped in many cases. For example, doing a specific business operation that results in a few tables being updated so that the results are recorded should be done synchronously.
But post-processing activities like sending notification emails, SMS, etc. can be delegated to an asynchronous subscriber by publishing them as events. This helps is isolating any failures that happen with such non-time-sensitive operations from impacting the main business process. We can also implement delayed processing or retry strategies in case their availability rates are lower.
Estimate the System Resources Required and Provision According
With a monolithic system, we would not know how much resources a specific piece of functionality would take. It is critical to quantify that by some means. We can instrument logging data for that portion of the monolith alone specifically and get to know the estimated traffic and time taken for the processing which can be used as the benchmark to adhere to. Based on this the new system resources can be allocated.
Auditing the Results of the Newly Implemented Components
This is to ensure the newly built components provide the same results after execution compared to the piece of functionality within the monolith. We normally do this by logging the results of that particular piece of functionality within the monolith and then routing some traffic in a fire-and-forget mode to the new component which would also log the results. Then we compare the results obtained from both sides to see if there are any discrepancies and address them if required.
A Throttled Ramp-Up of Traffic to the New Components
Once the audit results are satisfactory, we send a small % of traffic to the new component and start using the response for further processing within the normal control flow of the monolithic system. We observe the new system behavior for some time and then slowly increase the % of traffic.
Typically the non-functional issues like increase response time, connection drops, memory leaks, etc. would be brought to light slowly and can be fixed before sending in more traffic. By doing this we could still have the new system up and running serving traffic but still, manage the traffic levels to maintain a satisfactory level of performance.
Above are some common patterns that we generally use for the monolith to microservices migration journey. I can follow up on this article with a more detailed explanation for any of the above topics that are of specific interest.
Opinions expressed by DZone contributors are their own.
Trending
-
How To Design Reliable IIoT Architecture
-
Build a Simple Chat Server With gRPC in .Net Core
-
Getting Started With the YugabyteDB Managed REST API
-
Apache Kafka vs. Message Queue: Trade-Offs, Integration, Migration
Comments