Safely Modernizing a Monolith with AWS Migration Hub Refactor Spaces
By Collin Smith, Solutions Architect – Xerris
AWS Migration Hub Refactor Spaces is designed to help customers refactor existing Amazon Web Services (AWS) applications incrementally, while increasing business agility and time to market and maximizing the business value of AWS.
Designing and building the necessary infrastructure to refactor applications can be time consuming and expensive. This is where AWS Migration Hub Refactor Spaces comes in.
With Refactor Spaces developers will have the infrastructure they need to work so they can focus on extracting capabilities to help realize tangible value quickly.
In this post, I will demonstrate an actual upgrade of a monolithic application with AWS Migration Hub Refactor Spaces. This will include setting up the Migration Spaces environment and refactoring two microservices of the monolithic application.
The first microservice will be served from a separate virtual private cloud (VPC), and the second microservice will be implemented as a serverless AWS Lambda function.
I am a Certified Solutions Architect Professional with years of cloud migration experience at Xerris, helping many customers migrate to AWS. Xerris is an AWS Migration and Modernization Competency Partner specializing in cloud-native development and Kubernetes. Xerris has established itself as a thought leader that can guide AWS customers through the journey to reinvent themselves with cloud-native technologies.
Many organizations possess monolithic applications where the application is self-contained without the notion of a modular architecture. I will review some of the key problems facing organizations wishing to refactor their monolith applications.
First, upgrading monolithic applications requires a certain amount of heavy lifting involving additional infrastructure and networking for refactoring. This can involve a significant amount of time and cost to implement.
Secondly, risk is higher when upgrades are “all or none” where the newer version of the application is handled in a big-bang approach. This can make upgrades challenging and present unwanted risk to organizations.
Thirdly, upgrading an existing monolithic application does not help an organization decompose key features and allow them to be applied to key strategic functions for the organization. This means a lack of reusability.
AWS Migration Hub Refactor Spaces benefits customers in their refactoring efforts of existing monolithic applications in several key ways:
- Increase business agility.
- Faster time to market.
- Maximize business value.
- Avoid wasted time and effort building the infrastructure required for refactoring.
Figure 1 – AWS Migration Hub Refactor Spaces.
AWS Migration Hub Refactor Spaces helps facilitate this pattern by allowing the old system to remain in place until users are confident the new system is operating as expected. This offers customers benefits including agility, frequent releases, lower risk, and easier rollbacks.
This approach to application modernization aligns well to the Strangler Fig pattern introduced by Martin Fowler: “Gradually create a new system around the edges of the old, letting it grow slowly over several years until the old system is strangled”.
This approach offers an incremental and reliable process to refactoring code, and the old system remains in place until the new system is operating as expected. The AWS Refactor Spaces service helps make this possible.
The Refactor Spaces environment enables the communication between separate VPCs of the old (monolithic) and new (modernized) applications. This inter-VPC communication works with both multi-account or single account environments.
Refactor Spaces establishes an Amazon API Gateway, a Network Load Balancer, and an AWS Transit Gateway, where users can establish a default traffic route to the monolith environment to start. Backend web services can then be gradually replaced (via the Strangler Fig pattern) with different routes within the Refactor Spaces environment to the modernized (refactored) web services.
In this post, I will demonstrate the single account approach. The following diagram represents the starting architecture before creating the Refactor Spaces environment.
The MonolithVPC contains the monolith application, while the ModernizedVPC and MarketingEvents Lambda functions represent modernized web services to be integrated.
Figure 2 – Initial monolithic architecture and 2 modernized web services.
In this demonstration, our monolith application is a React application frontend and three Python web services for the backend. Additionally, we have two “modernized” web services that have been written to replace two of the original monolithic web services.
Figure 3 – Monolithic sales page pulling data from getSalesLeads.
For this demonstration, each web service has a data field indicating whether it’s part of the monolith or a refactored web service. This field will be displayed on the frontend as an indicator of the source data.
Figure 4 – getSalesLeads web service.
Once we set up the Refactor Spaces environment, we’ll work towards the goal architecture below. There will be a default route where all traffic flows through Refactor Spaces to the monolithic application to start.
We will then demonstrate how to apply the Strangler Fig pattern to replace microservices one by one without making changes to the monolithic application.
The code for this demonstration can be found on GitHub. This code contains the frontend web application written in React and the backend web services which are written in Flask-based Python.
Additionally, it will also create the refactored web services. The first being a Python web service hosted in an Amazon Elastic Container Service (Amazon ECS) container, and the second being a Lambda function.
We will now walk through the steps for our Refactor Spaces demonstration.
Step 1: Provision the Required Infrastructure
Download the code from the repository provided, set the necessary environment variables for the AWS account, and under the infra folder execute the script
terraform_exec.sh 1 where 1 is to deploy the infrastructure.
This will provision all the infrastructure and the application.
In our case, the frontend application is available at https://enterprise.hungrr.io/, or via the domain name system (DNS) record you have available.
Figure 5 – Initial infrastructure.
Step 2: Create the Refactor Spaces Environment
The result should be the following Refactor Spaces environment with an Amazon API Gateway, a Network Load Balancer, and an AWS Transit Gateway.
Figure 6 – Refactor Spaces infrastructure.
Step 3: Create the Default Service to Route Traffic
Here, the default route will be created where the backend services will be rerouted to a custom domain name that points to the Refactor Spaces API Gateway and have the default backend traffic flow through to the existing Application Load Balancer.
This will leave the application functionality unchanged, but all backend traffic will flow through the Refactor Spaces environment.
The following steps describe a bit more detail around this:
Step 3(a): Create Default Service with Default Route
This involves creating our first default route by creating the first services in the Refactor Spaces environment.
Step 3(b): Create Custom Domain Name within API Gateway
We then create a custom domain name in the Amazon API Gateway that we can point our backend.hungrr.io DNS record to. We can use the API Gateway custom domain name as a target for our backend.hungrr.io DNS record. This ensures all backend web service traffic flows through the Refactor Spaces environment.
Step 3(c): Update the DNS Record to Point to the Custom Domain Name
Now, we go to Hosted zones in Amazon Route 53 and click on our hungrr.io domain name. We’ll then edit the backend.hungrr.io DNS record to change the Value field from the Monolithic Load Balancer URL to be the API Gateway domain name produced in Step 3(b).
We give this a few moments to propagate properly. The result should be that all of the backend traffic now flows through the Refactor Spaces environment, as can be seen below. It should not change any visible changes to the end user, but this lays the foundation for intended refactoring.
Figure 7 – Refactor Spaces architecture with the default route configured.
There is no real change here with respect to the application functionality. This is the expected behavior with Refactor Spaces and the initial default route.
Figure 8 – Monolithic Sales Page with Refactor Spaces default route (no change).
Step 4: Replace the Monolith getSalesLeads Web Service
Here, we look to refactoring (or modernizing) our /v1/getSalesLeads web service with the web service that we have created in the ModernizedVPC. This web service is hosted within an Amazon ECS container.
The expectation is that the getSalesLeads web service will now be routed from the ModernizedVPC rather than the monolithic application. This is reflected in the frontend application and backend application as follows.
Figure 9 – Monolithic Application Sales page retrieving data with modernized web service.
The updated architecture with this new Refactor Spaces route can be seen below:
Figure 10 – Refactor Spaces with one refactored web service.
Step 5: Replace the Monolith getMarketingEvents Web Service
For our final web service update, we’ll update the /v1/getMarketingEvents web service to be served from the MarketingEvents Lambda function rather than from the MonolithicVPC endpoint.
Now, if we look at the Marketing page which is pulling data from the getMarketingEvents web services, we should see the following:
Figure 11 – Monolithic Marketing page retrieving modernized marketing data.
The resulting architecture can be seen below. We have the default route along with two web services that have been upgraded with separate, and new web services which are not part of the monolithic application.
Figure 12 – Final architecture with two refactored web services.
One last note for consideration, if we had a VPC that was configured with a route (VPN) to an on-premises application, a customer could also have their on-premises application refactored with Refactor Spaces as well. However, latency may be a concern with this approach.
The easy setup of Refactor Spaces can quickly determine if this is acceptable for the customer. Another approach would be to do a direct migration of the monolith application to the AWS environment followed by the modernization with Refactor Spaces.
I have shown you how to effectively upgrade existing web services in a monolithic application with AWS Migration Hub Refactor Spaces. This service helps organizations apply the Strangler Fig pattern to their existing monolithic applications.
By applying a microservices architecture to monolithic applications, organizations can increase business agility and reduce costs to show value earlier with reduced risk. This is done without any changes to the monolithic application itself.
Do not hesitate to reach out to us at xerris.com for more information about your organization’s cloud and digital transformation needs and how we can help you.
The content and opinions in this blog are those of the third-party author and AWS is not responsible for the content or accuracy of this post.
Xerris – AWS Partner Spotlight
Xerris is an AWS Competency Partner specializing in cloud-native development and Kubernetes. Xerris has established itself as a thought leader that can guide AWS customers through the journey to reinvent themselves with cloud-native technologies.