AWS Lift and Shift Project with vProfile

A practical multi-tier cloud deployment project where I migrated the vProfile application from a local setup to AWS using EC2, S3, Route 53, Application Load Balancer, and Auto Scaling.

One of the most useful hands-on projects I worked on while learning AWS was deploying the vProfile application using a lift-and-shift strategy. This project helped me connect many AWS services together in a real application flow instead of learning them as separate isolated services.

In simple words, lift and shift means moving an application from a local or traditional setup to the cloud without redesigning the whole application architecture. The goal is to get the same application running on cloud infrastructure first, and then later optimize or re-architect it if needed.

Main idea: keep the application architecture mostly the same, but move the infrastructure to AWS so it becomes easier to manage, scale, and automate.

What the Application Looks Like

The vProfile application is not a single-server setup. It is a multi-tier application with different components working together.

  • Tomcat for the application layer
  • MySQL for the database
  • RabbitMQ for messaging
  • Memcache for caching

In a local environment, these services can run on separate virtual machines. In this AWS project, I moved the same structure to the cloud and connected everything using AWS networking and managed services where appropriate.

Architecture on AWS

The architecture I built on AWS looked like this:

User ↓ Domain / DNS ↓ Application Load Balancer ↓ Tomcat App Server(s) ↓ Backend Services - MySQL - RabbitMQ - Memcache

This setup was supported by several AWS services:

  • EC2 for compute instances
  • S3 for storing the application artifact
  • Route 53 private hosted zone for internal DNS
  • ACM for HTTPS certificate management
  • Application Load Balancer for traffic routing
  • Auto Scaling Group for the app layer

Step 1: Creating Security Groups and Key Pair

The first major setup step was networking and access control. I created separate security groups for:

  • Load Balancer
  • Tomcat application instance
  • Backend services

This was important because each layer should only talk to the layer it actually needs. For example:

  • Internet traffic should reach only the load balancer
  • Load balancer should talk to Tomcat on port 8080
  • Tomcat should talk to MySQL, Memcache, and RabbitMQ only on their required ports

I also created a key pair so I could securely SSH into the EC2 instances for verification and troubleshooting.

Step 2: Launching the Backend and App Instances

I launched four EC2 instances:

  • db01 for MySQL
  • mc01 for Memcache
  • rmq01 for RabbitMQ
  • app01 for Tomcat

Instead of manually logging into each instance and installing software one by one, I used user data scripts. These scripts automated the initial setup during instance launch.

For the backend servers, I used Amazon Linux 2023. For the Tomcat app server, I used Ubuntu 24 because installing Tomcat from the package repository was more straightforward in that environment.

What I liked about this step: it showed me how automation reduces repeated manual setup work and makes infrastructure more reproducible.

Step 3: Setting Up Internal DNS with Route 53

The application needs to connect to backend services by name. In the configuration file, the app expects hostnames like:

db01.vprofile.in mc01.vprofile.in rmq01.vprofile.in

Instead of hardcoding IP addresses in the application configuration, I created a private hosted zone in Route 53 and mapped those names to the private IP addresses of the backend EC2 instances.

This is much better than using raw IPs because if an instance gets replaced later, DNS can be updated without changing the application code itself.

Step 4: Building the Artifact Locally

After the infrastructure was ready, I built the application artifact on my own computer. For this step, I needed:

  • JDK 17
  • Maven
  • AWS CLI

I updated the application configuration to make sure it pointed to the correct private DNS names, then built the artifact using:

mvn install

This generated the WAR file inside the target directory.

Step 5: Uploading the Artifact to S3

I created an S3 bucket to store the built WAR file. To upload from my laptop, I created an IAM user with S3 access, generated access keys, configured the AWS CLI locally, and then uploaded the artifact.

aws s3 cp target/vprofile-v2.war s3://your-bucket-name

This step made the artifact available in a central place so the app server could fetch it later.

Step 6: Deploying the Artifact to Tomcat

On the Tomcat EC2 instance, I attached an IAM role with S3 access. Then I installed AWS CLI on the app server, downloaded the WAR file from S3, and deployed it into Tomcat.

The deployment steps included:

  • Stopping Tomcat
  • Removing the default ROOT app
  • Copying the WAR file as ROOT.war
  • Starting Tomcat again

Once Tomcat extracted the WAR, the application became available on port 8080.

Step 7: Creating the Application Load Balancer

Next, I created a target group pointing to the Tomcat app server on port 8080 and configured health checks on the same port.

Then I created an Application Load Balancer and attached it to the correct security group. The load balancer was configured to forward traffic to the target group.

I also added HTTPS by attaching an ACM certificate to the load balancer listener.

User → HTTPS → Load Balancer → Tomcat

Step 8: Verifying the Full Application

After the load balancer was active and the target became healthy, I accessed the website through the load balancer URL and performed full application checks.

  • Login success confirmed database connectivity
  • RabbitMQ queue creation confirmed message broker connectivity
  • Repeated user access confirmed Memcache integration

This was one of the most satisfying parts of the project because it proved that the full end-to-end application stack was actually working on AWS.

Step 9: Converting the App Layer into Auto Scaling

After the manual app server worked correctly, I created an AMI from the app instance and used it in a launch template.

Then I created an Auto Scaling Group for the app layer. This meant the application instances could now:

  • Scale out when load increases
  • Scale in when load decreases
  • Replace unhealthy instances automatically

I also enabled target group stickiness because the vProfile application handles session-related behavior in a way that works better when the same user continues hitting the same instance.

What This Project Taught Me

This project taught me much more than just launching a few EC2 instances. It helped me understand how multiple AWS services work together as part of one application deployment flow.

  • How security groups enforce traffic flow between layers
  • Why internal DNS is important for service communication
  • How artifacts move from local machine to cloud infrastructure
  • How load balancing and health checks work together
  • Why Auto Scaling matters for production-style systems
Big takeaway: this was not just about “hosting an app.” It was about understanding how application deployment, networking, scaling, and automation fit together in a cloud environment.

Why This Was a Lift-and-Shift Project

This project is called lift and shift because the application architecture itself was not redesigned. The same core components were moved from a local or VM-based setup to AWS.

The next level beyond this would be re-architecting the application using more managed cloud-native services. But before doing that, this project gave a strong understanding of how a traditional multi-tier application behaves in AWS infrastructure.

Final Thoughts

For me, this was one of the most valuable AWS projects because it tied together many concepts that are often learned separately: EC2, S3, Route 53, IAM, Load Balancer, ACM, and Auto Scaling.

It also gave me confidence that I can follow a full deployment flow, troubleshoot integration issues, and think more practically about how real-world applications are migrated and run in the cloud.