In this article, we are going to cover Deploy Two Tier Architecture in AWS using Terraform.
We will introduce Terraform, an infrastructure-as-code tool, and demonstrate its use to deploy a two-tier architecture in AWS.
We will architect a Two Tier Architecture that consists of the following:
- A VPC with 2 public subnets and 2 private subnets.
- A load balancer that will direct traffic to the public subnets and 1 EC2 instance in each public subnet.
- An RDS MySQL instance in one of the subnets.
Table of Contents
What is AWS Two Tier Architecture?
AWS two-tier architecture is a common deployment pattern used for web applications in the cloud. It consists of two main components or tiers:
- Web Server Tier: This tier is responsible for serving web pages and handling user requests. It typically includes load balancers, web servers, and application servers. Let’s take a closer look at each of these components:
- Load Balancers: A load balancer distributes incoming traffic to multiple web servers, improving the performance and availability of the application. AWS provides two types of load balancers: Application Load Balancers and Network Load Balancers.
- Web Servers: Web servers are responsible for serving web pages to the user’s browser. They can handle static content such as HTML, CSS, and JavaScript. Web servers can also execute dynamic content, such as PHP, Python, or Ruby on Rails.
2. Database Tier: This tier is responsible for storing and managing data used by the web application. It typically includes a database server and associated storage. Let’s take a closer look at each of these components:
- Database Server: A database server stores and manages data used by the application. AWS provides a variety of database options, including Amazon Relational Database Service (RDS), Amazon DynamoDB, and Amazon Aurora.
- Storage: Storage is used by the database server to store data. AWS provides various storage options, such as Amazon Elastic Block Store (EBS), Amazon Simple Storage Service (S3), and Amazon Elastic File System (EFS).
The two tiers are separated by a firewall or security group to restrict access to the database server from the internet. This architecture is highly scalable, and fault-tolerant, and provides a separation of concerns between the web and database tiers.
Why do we use Two Tier Architecture?
Two-Tier Architecture is employed for web applications in the cloud due to several advantages:
- Simplicity: The architecture is straightforward with two distinct tiers (web and database), making it easier to design, deploy, and manage compared to more complex architectures.
- Scalability: The separation of the web and database tiers allows for independent scaling. This means that if the demand on the web servers increases, you can scale that tier without necessarily affecting the database tier, and vice versa.
- Performance: Load balancing in the web server tier enhances performance by distributing incoming traffic across multiple servers. This ensures efficient utilization of resources and improved response times for users.
- Fault Tolerance: The isolation of the web and database tiers contributes to fault tolerance. If one tier experiences issues or failures, the other can continue to function, minimizing the impact on the overall application.
- Security: By placing a firewall or security group between the web and database tiers, access to the sensitive database server from the internet is restricted, enhancing the overall security posture of the application.
Difference between AWS Two Tier and Three-Tire architecture:
Feature | Two-Tier Architecture | Three-Tier Architecture |
---|---|---|
Number of Tiers | Two: Web Server Tier and Database Tier | Three: Web Server Tier, Application (Logic) Tier, and Database Tier |
Responsibilities | – Web Tier: Serves web pages and handles user requests – Database Tier: Stores and manages data | – Web Tier: Handles user interface and presentation logic – Application Tier: Manages business logic – Database Tier: Stores and manages data |
Scalability | Independent scaling of web and database tiers | Independent scaling of web, application, and database tiers |
Flexibility | Limited separation of concerns between presentation and data | Clear separation of presentation, business logic, and data layers |
Complexity | Simpler design and management due to fewer tiers | More complex design but with added flexibility and scalability |
Performance | Load balancing improves performance in the web tier | Better optimization of performance with separate application tier |
Use Cases | Suitable for simpler applications with fewer scalability and flexibility requirements | Suited for complex applications with varying scalability needs and a clear separation of concerns |
Example AWS Services | – EC2 instances for web servers – RDS or DynamoDB for databases | – EC2 instances for web servers – ECS or Lambda for application tier – RDS, DynamoDB, or other databases for data storage |
Security | Firewall separates web and database tiers for access control | Firewall can be implemented between each tier for fine-grained access control |
Fault Tolerance | Isolation of tiers provides some fault tolerance | Better fault tolerance with separate application layer |
Maintenance | Easier to manage due to fewer components | Requires more careful management of three distinct layers |
Two Tier Architecture:

This two-tier architecture will contain the following components:
- Deploy a VPC with CIDR 10.0.0.0/16
- Within the VPC we will have 2 public subnets with CIDR 10.0.1.0/24 and 10.0.2.0/24. Each public subnet will be in a different Availability Zone for high availability
- Create 2 private subnets with CIDR ‘10.0.3.0/24’ and ‘10.0.4.0/24’ and each will be in a different Availability Zone
- Deploy RDS MySQL instance.
- An Application load balancer that will direct traffic to the public subnets.
- Deploy one EC2 instance in each public subnet for high availability.
- Internet Gateway and Elastic IPs for EC2 instance.
Prerequisites:
- Install AWS CLI
- AWS Account
- Code Editor (I have used VS Code for this deployment)
Steps for Implementation Two Tier Architecture in AWS using Terraform
Summary view of the terraform files in VS code:

Step 1:- Create provider.tf file
The provider.tf file in Terraform is a configuration file that specifies the cloud provider and its corresponding plugin that Terraform will use to manage resources in that provider.
Provider.tf file is used for the following:-
- Provider Declaration: Declares the cloud or infrastructure provider, such as AWS or Azure.
- Authentication Details: Includes credentials (e.g., access and secret keys) for connecting to the chosen provider.
- Region Specification: Specifies the geographic region where resources will be provisioned.
- Version Constraints: Optionally sets constraints on the provider version for compatibility.
- Additional Settings: May include other provider-specific configurations, like endpoints or custom parameters.
provider.tf
terraform { required_providers { aws = { source = "hashicorp/aws" version = "~> 4.16" } } } # Configure provider provider "aws" { region = "ap-south-1" profile="default" }

Step 2:- Create network resources.tf file
In Terraform projects, the network_resources.tf file plays a crucial role as it holds the configuration for the essential network infrastructure required by your application. This encompasses defining a Virtual Private Cloud (VPC) to establish an isolated network environment, configuring subnets, setting up an internet gateway, defining route tables, and orchestrating load balancers.
The network_resources.tf file is integral in a Terraform project, allowing the definition of two public and two private subnets, each tailored with unique configurations. Public subnets enable inbound internet traffic, while private subnets restrict inbound access to within the VPC.
This file extends its functionality to configure an internet gateway facilitating traffic between the VPC and the internet. It also outlines the setup of route tables and their associations, critical for routing traffic between subnets within the VPC.
Incorporating a load balancer with a listener and target group is another facet of network_resources.tf. This load balancer efficiently directs traffic to specific instances within the VPC, with the file specifying the attachment of a target group to the load balancer.
Additionally, network_resources.tf accommodates the configuration of an RDS database subnet group, designating subnets for RDS instances. This ensures proper isolation of RDS instances from other VPC resources.
network_resources.tf
# Create VPC resource "aws_vpc" "vpc" { cidr_block = "10.0.0.0/16" instance_tenancy = "default" tags = { Name = "vpc-project" } } # Create internet gateway resource "aws_internet_gateway" "ig" { vpc_id = aws_vpc.vpc.id tags = { Name = "ig-project" } } # Create 2 public subnets resource "aws_subnet" "public_1" { vpc_id = aws_vpc.vpc.id cidr_block = "10.0.1.0/24" availability_zone = "ap-south-1a" map_public_ip_on_launch = true tags = { Name = "public-1" } } resource "aws_subnet" "public_2" { vpc_id = aws_vpc.vpc.id cidr_block = "10.0.2.0/24" availability_zone = "ap-south-1b" map_public_ip_on_launch = true tags = { Name = "public-2" } } # Create 2 private subnets resource "aws_subnet" "private_1" { vpc_id = aws_vpc.vpc.id cidr_block = "10.0.3.0/24" availability_zone = "ap-south-1a" map_public_ip_on_launch = false tags = { Name = "private-1" } } resource "aws_subnet" "private_2" { vpc_id = aws_vpc.vpc.id cidr_block = "10.0.4.0/24" availability_zone = "ap-south-1b" map_public_ip_on_launch = false tags = { Name = "private-2" } }

Step 3:- Create security resources.tf file
The security_resources.tf file in Terraform is vital for configuring application security, focusing on security groups for EC2 instances and load balancers. Within this file, you define security group configurations for EC2 instances, specifying open ports and allowed protocols for inbound and outbound traffic.
For instance, you might permit HTTP and SSH traffic on ports 80 and 22, ensuring internet access for web traffic and SSH access from your local machine.
Additionally, security_resources.tf configures a security group for the load balancer, detailing rules for traffic between the load balancer and EC2 instances.
Proper configuration of this file is essential for a secure application, controlling traffic flow within and outside the VPC. This minimizes security risks, ensuring compliance with relevant regulations and standards.
security_resource.tf
# Security group for ALB resource "aws_security_group" "alb_sg" { name = "alb-sg" description = "security group for alb" vpc_id = aws_vpc.vpc.id ingress { from_port = "0" to_port = "0" protocol = "-1" cidr_blocks = ["0.0.0.0/0"] } egress { from_port = "0" to_port = "0" protocol = "-1" cidr_blocks = ["0.0.0.0/0"] } } # Create ALB resource "aws_lb" "project_alb" { name = "alb" internal = false load_balancer_type = "application" security_groups = [aws_security_group.alb_sg.id] subnets = [aws_subnet.public_1.id, aws_subnet.public_2.id] } # Create ALB target group resource "aws_lb_target_group" "project_tg" { name = "project-tg" port = 80 protocol = "HTTP" vpc_id = aws_vpc.vpc.id depends_on = [aws_vpc.vpc] } # Create target attachments resource "aws_lb_target_group_attachment" "tg_attach1" { target_group_arn = aws_lb_target_group.project_tg.arn target_id = aws_instance.web1.id port = 80 depends_on = [aws_instance.web1] } resource "aws_lb_target_group_attachment" "tg_attach2" { target_group_arn = aws_lb_target_group.project_tg.arn target_id = aws_instance.web2.id port = 80 depends_on = [aws_instance.web2] } # Create listener resource "aws_lb_listener" "listener_lb" { load_balancer_arn = aws_lb.project_alb.arn port = "80" protocol = "HTTP" default_action { type = "forward" target_group_arn = aws_lb_target_group.project_tg.arn } }
Step 4:- Create routetable_resource.tf file
The
routetable_resource.tf file in Terraform is responsible for configuring route tables, crucial for directing network traffic within a Virtual Private Cloud (VPC). By creating a route table to route traffic through the internet gateway we will give internet access to the VPC.
Key aspects include:
- Route Table Definition:
- Defines route tables to specify how network traffic is directed between subnets in the VPC.
- Route Associations:
- Associates route tables with specific subnets, determining how traffic flows within the VPC.
- Routing Rules:
- Specifies routing rules for each route table, determining the next hop for traffic based on destination CIDR blocks.
- Internet and Gateway Routes:
- Configures routes for internet-bound traffic, often involving an internet gateway, ensuring connectivity outside the VPC.
Proper configuration of the routetable_resource.tf file is essential for effective network routing within an AWS VPC, ensuring traffic is directed accurately between subnets and external destinations.
routetable_resource.tf
# Create route table to internet gateway resource "aws_route_table" "project_rt" { vpc_id = aws_vpc.vpc.id route { cidr_block = "0.0.0.0/0" gateway_id = aws_internet_gateway.ig.id } tags = { Name = "project-rt" } } # Associate public subnets with route table resource "aws_route_table_association" "public_route_1" { subnet_id = aws_subnet.public_1.id route_table_id = aws_route_table.project_rt.id } resource "aws_route_table_association" "public_route_2" { subnet_id = aws_subnet.public_2.id route_table_id = aws_route_table.project_rt.id } # Create security groups resource "aws_security_group" "public_sg" { name = "public-sg" description = "Allow web and ssh traffic" vpc_id = aws_vpc.vpc.id ingress { from_port = 80 to_port = 80 protocol = "tcp" cidr_blocks = ["0.0.0.0/0"] } ingress { from_port = 22 to_port = 22 protocol = "tcp" cidr_blocks = ["0.0.0.0/0"] } egress { from_port = 0 to_port = 0 protocol = "-1" cidr_blocks = ["0.0.0.0/0"] } } resource "aws_security_group" "private_sg" { name = "private-sg" description = "Allow web tier and ssh traffic" vpc_id = aws_vpc.vpc.id ingress { from_port = 3306 to_port = 3306 protocol = "tcp" cidr_blocks = ["10.0.0.0/16"] security_groups = [ aws_security_group.public_sg.id ] } ingress { from_port = 22 to_port = 22 protocol = "tcp" cidr_blocks = ["0.0.0.0/0"] } egress { from_port = 0 to_port = 0 protocol = "-1" cidr_blocks = ["0.0.0.0/0"] } }
Step 5:- Create ec2-resources.tf file
The ec2-resources.tf file in Terraform serves as a configuration file specifically designed for defining and provisioning AWS EC2 instances. Key components of this file include:
- Instance Configuration:
- Defines the characteristics of EC2 instances, such as instance types based on application requirements.
- Specifies the Amazon Machine Image (AMI) for launching instances, detailing the operating system and any additional software or configurations needed.
- Elastic IP Allocation:
- Allocates Elastic IPs, providing static public IP addresses for EC2 instances.
- Useful for scenarios requiring a consistent IP address, such as DNS records or firewall configurations.
- NGINX Web Server Configuration:
- Configures EC2 instances with NGINX web servers to serve web pages to users.
- Includes installation of NGINX software and necessary configurations for web page serving.
- Network Settings:
- Ensures proper network settings, connectivity, and accessibility from the internet for EC2 instances.
ec2_resources.tf
# Create ec2 instances resource "aws_instance" "web1" { ami = "ami-0287a05f0ef0e9d9a" instance_type = "t2.micro" key_name = "twotier-key-pair" availability_zone = "ap-south-1a" vpc_security_group_ids = [aws_security_group.public_sg.id] subnet_id = aws_subnet.public_1.id associate_public_ip_address = true tags = { Name = "web1_instance" } } resource "aws_instance" "web2" { ami = "ami-0287a05f0ef0e9d9a" instance_type = "t2.micro" key_name = "twotier-key-pair" availability_zone = "ap-south-1b" vpc_security_group_ids = [aws_security_group.public_sg.id] subnet_id = aws_subnet.public_2.id associate_public_ip_address = true tags = { Name = "web2_instance" } }
Use the below Linux Commands to Install Nginx On Both Ubuntu Instance Created:- sudo apt update -y sudo apt install nginx sudo systemctl enable nginx sudo systemctl start nginx


Step 6:- Create db-resources.tf file
Thedb-resources.tf file in Terraform is crucial for provisioning an RDS database in AWS. It configures a MySQL RDS database, specifying the instance class, allocated storage, and backup window. This file allows customization of database instance classes, storage types, and backup schedules to optimize performance, durability, and availability. Proper configuration is vital for ensuring the reliability, scalability, and data integrity of your application.
db_resources.tf
# Database subnet group resource "aws_db_subnet_group" "db_subnet" { name = "db-subnet" subnet_ids = [aws_subnet.private_1.id, aws_subnet.private_2.id] } # Create database instance resource "aws_db_instance" "project_db" { allocated_storage = 5 engine = "mysql" engine_version = "5.7" instance_class = "db.t2.micro" identifier = "db-instance" db_name = "project_db" username = "admin" password = "password" db_subnet_group_name = aws_db_subnet_group.db_subnet.id vpc_security_group_ids = [aws_security_group.private_sg.id] publicly_accessible = false skip_final_snapshot = true }

Step 7:- Let’s deploy!
- terraform init
The terraform init the command is used to initialize a new or existing Terraform configuration. This command downloads the required provider plugins and sets up the backend for storing state.

- terraform plan
The terraform plan the command is used to create an execution plan for the Terraform configuration. This command shows what resources Terraform will create, modify, or delete when applied.


- terraform apply
The terraform apply the command is used to apply the Terraform configuration and create or modify resources in the target environment.


- terraform destroy
The primary purpose of terraform destroy is to remove all the resources that were created by the Terraform configuration.


Step 8:- Go to the AWS console and verify
- VPC and Network resources

2. EC2 instances

3. Load Balancer

4. Target Group

5. RDS MYSQL Database

6. EC2 NGINX web server is also working fine


7. Security Groups

8. Create your own Html Page and try to reload the Url generated from the Load Balancer then you will find both the instance created are running successfully.
http://alb-313231715.ap-south-1.elb.amazonaws.com/


Conclusion:
Deploying a Two Tier Architecture in AWS with Terraform streamlines web application infrastructure. The separation of web and database tiers, orchestrated through Terraform’s declarative approach, enhances scalability and resilience. This efficient deployment ensures optimal resource allocation and accelerates the development lifecycle.
Reference:-
For reference visit the official website TerraformRegistry.
Any queries pls contact us @Devopshint.
Related Articles:
Terraform State File Management | Terraform Local State File | Terraform Remote State