In this post, I’ll walk through the architecture and implementation of a redesigned multi-tier web application hosted on AWS. This updated design leverages AWS-managed services such as Amazon MQ, RDS MySQL, and ElastiCache to enhance scalability, reliability, and ease of management. I also used AWS Elastic Beanstalk for deploying the front-end application. From setting up the infrastructure to securing and optimizing it, here’s a complete look at how I implemented the architecture.
Just before the implementation, let us see the importance and benefits of this architecture compared to the previous architecture which does not include AWS-managed services.
1. Enhanced Reliability with Managed Services
By adopting services like Amazon RDS for MySQL, Amazon MQ, and ElastiCache, we've minimized the need for manual intervention, reducing the risk of service outages and improving overall system stability. For example, RDS offers automated backups and failover support, ensuring the application can handle disruptions seamlessly.
2. Simplified Application Deployment with Elastic Beanstalk
Elastic Beanstalk automates application deployment, including autoscaling and load balancing. This allows us to focus on developing new features rather than managing infrastructure. For instance, the app can now auto-scale during high traffic, reducing the risk of downtime.
3. Optimized Global Performance through CloudFront
With CloudFront as our CDN, users from different regions experience faster load times by caching content closer to them. For example, users in Europe or Asia access cached content locally instead of waiting for data to travel from a single data center.
4. Improved Security and Compliance
Using AWS-native services strengthens security with automatic encryption and compliance controls. ACM certificates for HTTPS, combined with fine-grained IAM permissions, protect user data and comply with global standards.
5. Cost Efficiency through Automation
Elastic Beanstalk and managed services optimize resource use, which can reduce overall costs. For example, auto-scaling ensures we only pay for resources when needed, instead of maintaining idle servers.
Overall, this architecture improves user experience, scales effortlessly, and simplifies management, making it a sustainable solution for long-term growth.
Enhanced Implementation Outline with Steps:
1. Create Security Key Pairs and Security Groups
- Key Pair: Generate a key pair for SSH access should there be a need to access the EC2 instances.
-
Security Groups: Define security groups for:
-
Frontend (Elastic Beanstalk): I allowed Elastic Beanstalk to create this with inbound rules for HTTP (port 80) and HTTPS (port 443) on its
Application Load Balancer
. - Backend Services: I created one security group for RDS, Amazon MQ, and ElastiCache with rules that allow inbound access only from the Elastic Beanstalk environment. Also, I allowed all traffic from itself (the backend security group) so that each backend service can communicate with the other.
-
Frontend (Elastic Beanstalk): I allowed Elastic Beanstalk to create this with inbound rules for HTTP (port 80) and HTTPS (port 443) on its
2. Backend Services (RDS, Amazon MQ, ElastiCache)
-
Parameter Groups and Subnet Groups:
- RDS: Configure custom settings in a parameter group for optimized performance and create a subnet group for database availability.
- Amazon MQ and ElastiCache: Create separate parameter and subnet groups to set up specific configurations for Amazon MQ and ElastiCache.
-
Launch Instances:
- Launch RDS (MySQL), Amazon MQ (ActiveMQ), and ElastiCache (Memcached) instances with the backend security group.
3. Initialize Database on RDS
-
Ubuntu EC2 Instance:
- Launch an EC2 instance with SSH access to connect to RDS. This Ubuntu instance will be our
mysql client
. Ensure RDS security group (backend) allows traffic frommysql client
. - Once launched, SSH to the mysql client, update packages, and install necessary tools like git to clone the repository containing database files.
- Launch an EC2 instance with SSH access to connect to RDS. This Ubuntu instance will be our
ssh -i "abc-keypair.pem" ubuntu@ec2-35-179-168-111.eu-west-2.compute.amazonaws.com
sudo -i
apt update && apt install mysql-client git -y
-
Database Initialization:
- Clone the repository that contains the database info and switch to the branch
awsrefactor
, which containdb_backup.sql
from here.
- Clone the repository that contains the database info and switch to the branch
git clone repourl
git checkout awsrefactor
Import the db_backup.sql file into the accounts
database on a MySQL server hosted on Amazon RDS
mysql -h [RDS endpoint] -u admin -p accounts < src/main/resources/db_backup.sql
- Verify tables using MySQL commands; then terminate the
mysql client
instance if needed because we don't need it anymore.
mysql -h [RDS endpoint] -u admin -p accounts
show tables;
4. Set Up Elastic Beanstalk Environment
-
Service Role Creation: Create a role with permissions (
AdministratorAccess-AWSElasticBeanstalk
,AWSElasticBeanstalkCustomPlatformforEC2Role
,AWSElasticBeanstalkRoleSNS
,AWSElasticBeanstalkWebTier
) to manage Elastic Beanstalk and handle S3 and SNS notifications. -
Setting Up Elastic Beanstalk Environment:
- Choose Tomcat 10 with Corretto 21 on Amazon Linux 2023.
- Configure health checks on
/login
. - Set up HTTPS listener on port 443 for the Elastic Load Balancer (ELB).
- Update Backend Security Group: Allow traffic from Elastic Beanstalk to the backend services (RDS, MQ, and ElastiCache).
- Artifact Deployment: Deploy your built web application, including backend information, to Elastic Beanstalk. I simply uploaded the artifact from my system to Elastic Beanstalk. However, you can also upload to S3 and point Elastic Beanstalk to the bucket containing the file. See the process to build the artifact and also upload it to S3 in this project.
Beanstalk Environment Launched
6. Set Up CloudFront and SSL Certificate
- SSL Certificate: Request an SSL certificate in us-east-1 for CloudFront distribution.
-
CloudFront Distribution:
- Create a CloudFront distribution and set the Elastic Load Balancer as the origin domain.
- Enable HTTP and HTTPS protocols for improved compatibility and security.
- DNS Mapping: Use Route 53 to create a CNAME record in the public hosted zone, linking the CloudFront endpoint to the App custom domain.
CloudFront endpoint mapped to App domain name in Route53
7. Testing and Verification
- Application Testing: Access the application via the custom domain to confirm traffic routing through CloudFront.
- CloudFront Validation: Use development tools or AWS CloudFront analytics to ensure CloudFront is serving content.
App is reachable on HTTP port 80 and HTTPS port 443
App connected to backend services
Mozilla Firefox showing traffic is coming into the App via AWS CloudFront
8. Challenges & Lessons Learned
I learned a lot from this project but one stood out - checking documentation
first before considering other resources. I ran into issues creating my Elastic Beanstalk Environment. I saw the notification that launch configuration
is now deprecated in favour of launch template
from October 1, 2024 details here. However, I thought I would breeze through and consult other resources including ChatGPT
which proffered some complex solutions. I managed to crack it by checking AWS Elastic Beanstalk documentation after spending a few hours researching other resources. See the error screenshots below.
Conclusion
Building this multi-tier web application with AWS-managed services provided me with valuable insights into scalable architecture, automated deployment, and cloud security. Leveraging services like Amazon MQ, RDS MySQL, and ElastiCache simplified management and improved performance. Using Elastic Beanstalk for deployment streamlined the process and provided built-in support for scaling and load balancing.
For future enhancements, I may decide to containerize my application with further automating deployment with CI/CD pipelines, or exploring serverless options for even greater scalability and cost efficiency.
Top comments (0)