MIGRATING FROM MONOLITH TO MICROSERVICES: STRATEGY & STEP-BY-STEP GUIDE
Migrating from monolith to microservices is less costly and risky than?redeveloping an entire system from scratch. But don’t get your hopes high — the migration process is full of technical and organizational challenges.
A successful migration requires in-depth infrastructure assessment, decomposition of your monolith architecture, software refactoring, and thorough testing. Your teams should also understand the specificity of distributed computing and continuous deployment to take full advantage of the?architecture.
So, what are the?advantages of a microservices architecture, should you convert to it, and how do you proceed with the migration?
Monolith architecture and microservices
A?monolith architecture?is an application with a single code repository for software modules, business logic, and data access. A typical monolith is a collection of tightly coupled services deployed and managed in one place.
Microservices?is a software architecture that distributes systems in independent components with specific functions, computing resources, and databases. This architecture emphasizes loose coupling and high cohesion, meaning each component can be deployed and upgraded in isolation. The components use application programming interfaces (APIs) to exchange data.
Why should you migrate to microservices?
Monolith systems tend to get more complex as you add new features, and this can quickly become an obstacle to your growth. Tight coupling prevents you from scaling system components independently and complicates testing, and your teams will also have a harder time maintaining the code due to hidden dependencies.
But moving from monolith to microservices offers some excellent business and technical benefits.
Business flexibility
Microservices architecture emphasizes bounded context between its independent components, making your system easily modifiable. It takes much less effort to add, remove, and upgrade features based on your business needs. So, it’s easier to keep systems relevant and competitive.
Faster deployment
Microservices code is more comprehensible because it’s restricted to a single data repository. Your teams will understand the dependencies and know what to expect when modifying the codebase. This makes testing more consistent and coherent, saving you time and money on upgrading the system.
Productive environment
Defined boundaries and minimal dependencies allow teams to implement, scale, and deploy multiple microservice simultaneously. It also means your developers have more autonomy. For example, they can choose programming languages, frameworks, and APIs that are better suited for their goals, further improving their productivity.
Fault tolerance
Modification in one module can break the entire monolith application, but things are the other way around in loosely-coupled architecture. Each microservice isolates its code errors and limits their impact on the whole system. This means that migrating from monolith to microservices makes your system more tolerant to failures.
Scalability
Companies can?scale microservices?in isolation based on their needs without affecting the rest of the application. What does this mean? You can improve performance for specific software modules by scaling computing resources up or back down.
All these benefits make microservices look like every app should be based on this architecture style. But don’t rush your conclusions. Let’s look at the intricacies of microservices that can make you hold off the migration.
When you shouldn’t go from monolith to microservices?
Microservices solve many problems of the monolith applications, but they aren’t a silver bullet for everyone. Their advantages come with certain issues we must address. They include:
These problems demonstrate that microservice architecture isn’t always beneficial for startups and midsized companies. Developing your system as a monolith might even be an excellent starting point.
Monolith is great for greenfield projects focused on exploratory development. It lets your developers explore functional and non-functional requirements, technical capabilities, and system boundaries. Smaller teams might prefer monolithic systems due to fewer moving parts and simplicity. They might also help you build minimal viable products or a proof of concept much faster than microservices.
Refactoring a monolith to microservices becomes necessary as your team expands. You’d want team members to be more autonomous if they plan to deploy services more frequently. A loosely-coupled architecture allows multiple departments to work on different products simultaneously.
Companies can modularize their monolithic architecture by setting boundaries for different components. Modules in the system will share the same code base, but the dependencies will be minimal. This will help you?divide these modules?into fully independent microservices when the time comes.
Choosing the strategy to migrate monolith to microservices
A migration strategy will help you move the applications with minimal errors. Now, there are many ways to convert monolith to microservices, but we like to focus on the most effective approaches.
Microservices are designed around business capabilities. Begin by assessing the large-scale structure of your monolith system and identity functionality. This might be challenging if your functionality is scattered across the monolith architecture, but it’s just the beginning.
Next, you should group functionality into bounded contexts — sets of closely related features and business functions. Here’s an example. You can put the customer loyalty, user rating, and accounts functionality into the “account” context, while drone sharing, predictive analysis, and drone repair will become the “drone management” group.
Migrating hundreds of services isn’t an option unless you want the entire system to collapse. Instead, it’s better to take an incremental approach to refactoring monolith to microservices.
You should specify features you want to migrate and prioritize first-movers. Then, you can remove dependencies between the bounded contexts and isolate them into separate modules.
How should you move the isolated features into the new system? Here are the two most popular approaches:
Pick the one that suits your organization’s structure, migration scope, and business goals. In some cases, combining the approaches can yield even better results.
Thus far, we’ve outlined the general strategy and approaches.
Now, it’s time to dive into the process.
Microservice migration: A step-by-step guide
Step 1: Assess readiness for migration
A successful migration requires analyzing the current infrastructure, internal policies, and team competence. Some of the attention points to consider include:
The assessment lets you understand what areas of your company need improvements before you can start identifying features to migrate.
Step 2: Identify functions and dependencies
Code in monolith architecture often accretes, which makes it too complex and full of hidden dependencies. For example, code for payment service can go to external payment providers, load irrelevant libraries, or hit retired processes.
Start by inventorying your functions and business capabilities. You architects should also find code objects associated and map them to business functions in the system.
Each microservice must serve a specific function and have a single data repository. So, you must retire applications that duplicate each other’s functionality or provide similar data from multiple locations.
Step 3: Select migration candidates
Determine which bounded context (functional groups) provide the most value as microservices and which you should leave in the monolith system for the time being.
领英推荐
Bring your engineers and domain experts for event storming. The developers will give you insights into the existing implementations, dependencies, and internal events. The non-technical experts will tell you about things missing in your services or features that might be critical in the future.
It would also help you select functionality and determine boundaries for your services. For example, a payment service group should include modules for payment authorization, refund, payment cancellation, and payment status checks. You might exclude related services with different domain areas, like order status, inventory check, and package tracking.
Step 4: Prioritize services for migration
Moving services incrementally helps you detect and handle issues as they arise. So, you need to identify components to move first.
What should you prioritize? Start with edge services — bounded contexts with fewer dependencies that are likely to be easiest to decompose into smaller services. These could include order management, invoicing, or notifications features.
You might also migrate monolith to microservices to address pressing problems. For example, focus on the most used services that cause performance bottlenecks in your monolith.
Step 5: Select a scalable infrastructure
Microservices architecture requires a platform that supports the scalability needs of your teams. One of the best solutions would be to use a serverless infrastructure hosted by cloud providers (like?Google Cloud, Microsoft Azure, and Amazon Web Services).
They let you easily scale resources for microservices and even support autoscaling. The flexible pay-as-you-go billing means you don’t pay for the resources you don’t use. You also get secure communication protocol and authorization tools to safeguard your corporate data. Additionally, the providers take care of the infrastructure maintenance for you.
Step 6: Separate the application’s layers
Traditional applications tend to be core components intertwined with domain logic. So, you need to separate the presentation, business logic, and persistence (data) layers of your monolithic applications when migrating to microservices.
As you divide the layers, you’ll need to set up gateway APIs that route requests between the client and backend. The API sets the boundaries between layers, helping your teams decouple and isolate the application. It also deals with cross-cutting tasks, such as SSL termination, authentication, and rate-limiting.
Step 7: Set up communications
Effective communication ensures exchange between different services in the loosely-coupled architecture. The primary messaging patterns include synchronous communication (where the caller waits for a response) and asynchronous messaging (the service can send multiple messages simultaneously). We recommend switching to asynchronous as you move more applications to microservices.
Your team also needs to set up appropriate public APIs (for client application calls) and backend APIs (for interservice communication). A public API should be compatible with your mobile and?web applications. You need to factor in latency, network performance, and payload size when selecting an API for the backend.
REST over HTTP/HTTPS is usually the optimal pattern for the client-side. As for the server-side, your options include RESTful interfaces (focused on stateless communications and scalability) and RCP interfaces (oriented towards commands and operations).
Step 9: Migrate data
As we mentioned, each microservice must have dedicated storage. So, the next step includes?moving legacy databases, logic, and behavior that support the application.
Some applications will also need to access old data from your monolith (primarily in a phased adoption approach). You need to configure an API to gather information from other services. This way, the payment microservice can fetch data from the profile module in the monolith.
Step 10: Create a CI/CD pipeline
You won’t get the most out of the new architecture without well-oiled continuous integration (CI) and continuous delivery (CD) processes. The CI allows your team to automatically test changes to always keep the code production-quality. CD tools help your teams automatically publish the code changes to the production environment.
Both techniques allow your teams to code, test, and deploy applications in the loosely-coupled architecture without disrupting each other. It’s also an excellent way to speed up the microservices migration process.
Step 11: Implement and deploy
Deploy the functionality gradually to ensure everything works as expected in the new architecture. Unfortunately, you might identify a significant semantic difference between the legacy system and the new one. Here’s how you can solve these problems.
Use an?anti-corruption pattern?(glue code) — a layer that translates communication between the existing monolith and a new system. It helps you ensure you transfer only the data required by the microservice, basically filtering unnecessary data that might pollute your system.
The?canary release?technique can help you reduce performance issues and errors when moving from monolith to microservices. Let’s say you migrated the application with a phased approach. First, send the traffic to the new microservice to a limited number of users (5%). If there are no errors, you can progressively increase the user number up to 100% before switching fully to a microservice.
After refactoring the application into a consistent microservice, you can remove the glue code and retire the monolith components. Then, rinse and repeat until everything service finds its way to your?scalable architecture.
And there you have it! Though the process of migration is long and strenuous, we hope you’re happy with the result.
Conclusion
Migrating from monolith to microservices is inevitable for growing companies industry-wide. The traditional monolithic architecture simply doesn’t provide the scalability, flexibility, and efficiency their teams need.
The migration process itself can be complicated, especially with outdated systems and unorganized legacy code. So, having the right strategy and approach can save you a lot of time, effort, and costs.
Cloud Consultant @ Deloitte Innovation Hub EMEA | Cloud & Infrastructure Automation ??
2 年from my perspective and what i read Ahmed El-Sayed i believe that move from monolithic to Microservices is the core usage of kubernetes and Containerization technology