Introduction
Deploying an application to AWS is more than launching a few EC2 instances and making the application accessible over the internet. A production-oriented deployment must consider network isolation, security, availability, scalability, load balancing, database resilience, and operational troubleshooting.
In this project, I deployed a full-stack Book Review Application using a three-tier architecture on AWS. The architecture separates the application into Presentation, Business, and Data tiers, with controlled communication between each layer.
The final traffic flow is:
Internet --> Public ALB --> Web Tier --> Internal ALB --> Application Tier --> Database Tier
The objective was to build an architecture where each tier has a clearly defined responsibility and can be secured, scaled, and maintained independently.
Architecture Overview
The deployment consists of three primary layers:
๐ Web Tier
The Web Tier hosts the Next.js frontend on Ubuntu EC2 instances, with Nginx configured as a reverse proxy. The public ALB distributes incoming HTTP traffic across healthy Web Tier instances deployed across multiple Availability Zones.
Nginx serves the frontend and can route backend/API requests through the internal ALB, which then forwards traffic to the private Node.js/Express instances.
The request flow is:
Client โ Public ALB โ Nginx โ Internal ALB โ Node.js App Tier โ RDS
This design keeps the Application Tier private while allowing the frontend to communicate with backend services through a controlled internal path, providing security, load balancing, scalability, and fault isolation.
โ๏ธ Application Tier
The Application Tier hosts the Node.js/Express backend on port 3001, deployed across EC2 instances in private subnets.
An internal Application Load Balancer distributes API traffic from the Web Tier across healthy application instances.
Because the Application Tier is private, the backend is not directly exposed to the internet. This provides a controlled communication path between the frontend and backend while allowing the application layer to scale independently.
๐๏ธ Data Tier
The Data Tier uses Amazon RDS for MySQL deployed in private subnets with restricted access from the Application Tier.
A Read Replica was used to offload read-heavy workloads from the primary RDS instance and provide additional read scalability, while Multi-AZ was used to improve high availability and failover.
This design protects the database from direct public access while providing availability, resilience, and controlled database connectivity.
VPC and Network Architecture
The foundation of the deployment is a custom Amazon VPC using:
VPC CIDR: 10.0.0.0/16
The VPC was divided into six subnets across two Availability Zones:
| Tier | Availability Zone A & CIDR Block | Availability Zone_B & CIDR Block |
|---|---|---|
| Web | Web_Public_SubnetA (10.o.1.0/24) | Web_Public_SubnetB (10.0.2.0/24) |
| Application | App_Private_SubnetA (10.0.10.0/24) | App_Private_SubnetB (10.0.12.0/24) |
| Database | DB_Private_SubnetB (10.0.20.0/28) | DB_Private_SubnetB (10.0.22.0/28) |
This subnet segmentation creates clear network boundaries between the three application layers.
The Web Tier requires public connectivity because it receives traffic from the internet through the public ALB.
The Application Tier remains private because it should only receive traffic from the Web Tier through the internal ALB.
The Database Tier is also private and should only accept database connections from the Application Tier.
Security Group Design
Security Groups were configured using a least-privilege approach.
The major security rules are:
| Component | Port | Source |
|---|---|---|
| Web-EC2-SG | 80 | Internet |
| App-EC2-SG | 80, 3001 | Web-EC2-SG, App-EC2-SG |
| RDS-DB-SG | 3306 | App-EC2-SGSG |
This avoids unnecessary CIDR-based access between tiers and ensures that each component only accepts the traffic required for its role.
Most importantly, the Application and Database tiers are not directly accessible from the public internet.
Web Tier Deployment
The Web Tier was deployed on Ubuntu EC2 instances running the Next.js frontend, with Nginx configured as a reverse proxy. Nginx receives HTTP requests on port 80 and routes them to the appropriate frontend or backend service.
The public ALB performs health checks against the Web Tier and distributes requests only to healthy instances.
Running multiple instances across Availability Zones reduces dependence on a single EC2 instance and provides a foundation for horizontal scaling.
Application Tier Deployment
The backend was deployed using Node.js and Express.
The application listens on:
Port: 3001
The backend instances are located in private subnets and are registered with the internal ALB.
The internal ALB provides load distribution between backend instances while keeping the API servers inaccessible from the public internet.
This separation also allows the Application Tier to scale independently of the Web Tier.
Database Deployment with Amazon RDS
The database layer uses Amazon RDS for MySQL.
The RDS instances are deployed using a DB subnets configuration spanning the private database subnets.
The database is not publicly accessible.
The RDS Security Group permits MySQL traffic only from the Application Tier.
This provides an additional security boundary between application logic and persistent data.
Multi-AZ and Read Replica
Two database concepts are particularly important in this architecture: Multi-AZ and Read Replicas.
They solve different problems.
- Multi-AZ: Multi-AZ is primarily used for high availability and failover.
If the primary database instance becomes unavailable, AWS can fail over to the standby instance.
The goal is therefore resilience rather than increasing read capacity.
- Read Replica: A Read Replica is primarily used for read scalability.
For workloads with a large number of read operations, suitable read traffic can be directed to the replica rather than sending every query to the primary database.
This can reduce read pressure on the primary database and provide additional capacity for read-heavy workloads.
A key distinction is:
Multi-AZ = high availability
Read Replica = read scalability
The Read Replica should therefore not be presented as the primary failover mechanism for the database.
Why This Architecture?
The primary reason for using a three-tier architecture is separation of concerns.
Each tier has a specific responsibility:
Web Tier: presentation and user interaction
Application Tier: business logic and API processing
Data Tier: persistent data storage
This separation provides several operational advantages.
Security: Private application and database tiers reduce the attack surface.
Scalability: Each tier can be scaled independently according to its workload.
Availability: Multiple Availability Zones, load balancing, and database redundancy reduce single points of failure.
Maintainability: Changes to one layer can be managed without unnecessarily affecting the others.
Fault Isolation: A failure in one component does not automatically require the entire application to be unavailable.
Key Takeaways
This deployment reinforced several core cloud and DevOps principles:
Security: Don't expose components unnecessarily. Control communication using least-privilege access.
Scalability: Design components so they can scale independently.
Availability: Eliminate unnecessary single points of failure through redundancy and Multi-AZ architecture.
Automation and repeatability: Infrastructure and application deployment should eventually become reproducible rather than dependent on manual configuration.
Observability and troubleshooting: Understanding how traffic moves through the system makes failures easier to isolate and resolve.
Most importantly, I learned that cloud engineering is not simply about deploying AWS services.
It is about understanding how those services work together to create a secure, reliable, scalable, and maintainable system.
Conclusion
The completed architecture provides a production-style foundation for the Book Review Application:
The project provided hands-on experience across AWS networking, EC2, Application Load Balancers, Nginx, Node.js, Next.js, RDS, security groups, private networking, high availability, scalability, and troubleshooting.
More importantly, it shifted my thinking from simply deploying an application to engineering the platform that the application runs on.
P.S. This post is part of the DevOps Micro Internship (DMI) with Agentic AI โ Cohort 3 โ by Pravin Mishra. My graded progress is public: https://dmi.pravinmishra.com/s/Tobilee10.html ยท Start your DevOps journey: https://dmi.pravinmishra.com/?utm_source=student&utm_medium=ps-linkedin&utm_campaign=cohort3



Top comments (0)