When it comes to monolithic designs, it's often difficult to have it resilient, fault tolerant and scalable compared to decoupled architecture. In this example, we have an EC2 Instance where the frontend, application, and database are all hosted. The goal of this project is to demonstrate the challenges with this architecture and re-architect it to a better design.
Challenges with Tightly Coupled Architecture
1. Scalability
In the first iteration of this project, the single EC2 Instance was responsible for all aspects of the application including the application storage tier, database tier, business logic tier.
This design limits the ability to handle increased traffic. Scaling vertically (upgrading instance size) was the only option, which is expensive and has physical limits.
2. Fault Tolerance
A single point of failure meant that if the EC2 instance went down, the entire application—including the database and media files—would become unavailable.
3. Resilience
With both the database and WordPress files on the same instance, data loss was a real risk in case of instance failure. There was no mechanism for data redundancy.
Recovery would require recreating the instance, restoring the database, and re-uploading media files, leading to significant downtime.
These are the major ones with the original architecture. I would have to mention maintenance activities like patching being extremely difficult and risky, static hard-coded configurations like public IP in WordPress, and operational overhead as honorable mentions as well.
How the New Architecture Addresses These Challenges
1. Enhanced Scalability
An Auto Scaling Group (ASG) for the EC2 application tier and an Application Load Balancer (ALB) for distributing traffic, allows us to horizontally and dynamically scale out or in, giving us the flexibility to have a mechanism for dynamic workloads.
2. Improved Fault Tolerance
A managed Database instance like Amazon RDS, which offers high availability with automatic failover allows us to have a more fault-tolerance architecture. In case anything happens to the EC2 Instance(s), your data is safe. RDS is redundant with multiple copies kept in different availability zones, and AWS manages the maintenance activities like patching and backup for you.
In this architecture, we also replace local storage with Amazon EFS for media files. That provides redundancy across multiple AZs, dynamic scalability in case our data grows, and it can be utilized by multiple compute sources like EC2 in case we need to scale out. And even if an EC2 instance fails, the media files remain available. The ASG automatically launches replacement instances, minimizing downtime.
3. Increased Resilience
Separated the database and media files from the EC2 instance and stored them in managed services designed for durability.
Impact: Data is no longer tied to the lifecycle of the EC2 instance. Backups and redundancy features in RDS and EFS ensure data integrity and quick recovery.
Honorable mentions for benefits would be less overhead for maintenance and scaling activities.
So, with all of this in mind, let's get to the execution!
1. Setting Up the Environment
First things first—getting the infrastructure up and running.
CloudFormation Template: Deployed a CF template to provide the foundational environment.
EC2 Instance: Launched an EC2 instance for the application tier.
Parameters in Systems Manager: Configured WordPress-related parameters like database credentials, DB Endpoints, for seamless management.
Initial Setup for EC2 Instance:
Installed prerequisites using Bash scripts to install WordPress and MariaDB.
Deployed WordPress and connected it to a local MariaDB instance using a public IP.
Ran tests (yes, dog pictures were involved 🐾).
Challenge: The hardcoded public IP caused issues whenever the IP changed. Clearly, this wasn't sustainable.
2. Introducing Launch Templates
Why Launch Templates Matter:
Manually configuring instances is not only error-prone but also doesn't scale well. In order for us to make horizontally scaling seamless, a launch template is extremely valuable. It provides consistency and ensures that every new instance has the same setup.
Created a launch template to streamline EC2 instance deployment.
Deployed a new instance using the template and repeated the WordPress initial setup steps.
3. Migrating the Database to RDS
The next step was to decouple the database from the EC2 instance.
Since we want to have a multiple AZ setup, I started off with creating a subnet group where it included 3 subnets from different availability zones.
High Level Database Migration Steps
Backed up the local MariaDB database.
Updated the DB endpoint parameter in Systems Manager to point to the RDS instance.
Restored the backup to the RDS instance.
Configured WordPress to use the RDS endpoint and stopped the local MariaDB service.
Ran tests to confirm the setup was working seamlessly.
4. Moving Media Files to Amazon EFS
Local storage wasn't cutting it. To make the design more resilient, media files were migrated to an Elastic File System (EFS).
Data Migration Process:
Created the EFS Filesystem in application subnets.
Installed EFS utilities on the EC2 instance.
Moved media files from the EC2 instance to a temporary folder.
Mounted the EFS filesystem to the WordPress wp-content folder.
Transferred media files back to wp-content and rebooted the instance.
Tested to ensure WordPress was serving media files from EFS.
5. Adding Elasticity with a Load Balancer
What’s scalability without elasticity? This step involved introducing a load balancer and autoscaling capabilities.
Application Load Balancer involved completing the steps below:
Created an Application Load Balancer (ALB) with a target group.
Updated the launch template to reference the ALB DNS name instead of the EC2 public IP.
Autoscaling Group:
Configured an Autoscaling Group (ASG) to manage EC2 instances dynamically.
Added scale-in and scale-out policies based on CPU utilization.
Observed the ASG spin up new instances and scale down as required.
Final Words
This project transformed a single-instance WordPress setup into a robust decoupled architecture. By separating the compute, database, and storage layers, the design became scalable, fault-tolerant, and resilient. The addition of a load balancer and autoscaling ensured elastic performance, while the use of managed services like RDS and EFS reduced operational overhead.
This architecture serves as a blueprint for modernizing legacy applications while maintaining cost efficiency and high availability. For specific instructions on how to complete each step, make sure to check out this GitHub Repository, here :
https://github.com/acantril/learn-cantrill-io-labs/tree/master/aws-elastic-wordpress-evolution
If you’ve got questions or want to discuss this project further, feel free to reach out!
Top comments (0)