On Day 26 of the Terraform Challenge, I moved from deploying static infrastructure to building a scalable web application architecture on AWS using Terraform. This project brought together EC2 Launch Templates, an Application Load Balancer, an Auto Scaling Group, and CloudWatch alarms into a modular infrastructure design that can automatically respond to changes in demand.
This was one of the most practical labs in the challenge because it demonstrated how multiple Terraform modules can work together to create a production-style environment where traffic is distributed across healthy instances and scaling decisions happen automatically.
Project Architecture
The infrastructure was split into three reusable Terraform modules:
EC2 Module
This module created the launch template and security group for the web application instances.ALB Module
This module provisioned the Application Load Balancer, listener, target group, and the ALB security group.ASG Module
This module created the Auto Scaling Group, attached instances to the ALB target group, and configured CPU-based scaling policies with CloudWatch alarms.
By separating the resources into modules, the deployment stayed organized and reusable. Each module focused on one responsibility, and outputs from one module were passed as inputs to another.
Why Modular Design Matters
Instead of placing all AWS resources in one Terraform file, I separated them into modules so that each part of the infrastructure could be reused independently.
For example:
- The EC2 module outputs the launch template ID
- The ALB module outputs the target group ARN
- The ASG module consumes both outputs to launch instances and attach them behind the load balancer
This modular structure keeps the environment configuration clean and makes it easier to maintain or expand the infrastructure later.
The envs/dev configuration only needed to define environment-specific variables like:
- AMI ID
- desired capacity
- subnet IDs
- VPC ID
All the infrastructure logic remained inside the modules.
Deployment Workflow
After building the modules, I deployed the infrastructure using the normal Terraform workflow:
terraform initterraform validateterraform planterraform apply
Terraform created:
- EC2 Launch Template
- Application Load Balancer
- Target Group
- Auto Scaling Group
- CPU scale-out and scale-in policies
- CloudWatch alarms
After deployment, Terraform returned the ALB DNS endpoint, which served as the public URL for the application.
When I opened the ALB URL in the browser, the application returned:
Deployed with Terraform — environment: dev
This confirmed that:
- the EC2 instances launched successfully
- the load balancer was routing traffic correctly
- the Auto Scaling Group registered healthy targets
How Auto Scaling Works
The Auto Scaling Group was configured with:
- minimum capacity: 1 instance
- desired capacity: 2 instances
- maximum capacity: 4 instances
CloudWatch alarms monitored average CPU utilization:
- If CPU reached 70%, Terraform triggered a scale-out policy to add one instance
- If CPU dropped to 30%, Terraform triggered a scale-in policy to remove one instance
This creates elasticity in the infrastructure, allowing the application to handle increased load while reducing costs during low usage.
One important configuration in the Auto Scaling Group was:
health_check_type = "ELB"
This setting ensures that scaling decisions are based on the Application Load Balancer health checks rather than only EC2 instance status.
Without it, an EC2 instance could remain "healthy" from AWS's perspective even if the web server application had failed. Using ELB health checks ensures only working instances receive traffic.
Benefits of This Architecture
This infrastructure design provides several key advantages:
1. High Availability
The Application Load Balancer distributes requests across multiple instances, reducing the risk of downtime.
2. Elastic Scaling
The Auto Scaling Group increases or decreases capacity based on CPU demand automatically.
3. Modular Reusability
Each module can be reused in other environments such as staging or production.
4. Maintainability
Because the modules are separated by function, updates can be made without affecting unrelated components.
5. Cost Efficiency
Scaling policies ensure resources are only added when needed.
Cleanup
Once the deployment was verified, I ran:
terraform destroy
This removed the Auto Scaling Group, load balancer, target group, launch template, and CloudWatch alarms.
Cleaning up after testing is important because EC2 instances and ALBs continue incurring charges if left running.
Final Thoughts
This project was a major step forward in understanding how scalable infrastructure is built on AWS with Terraform.
It was not just about provisioning EC2 instances, but about connecting multiple services into a self-managing system:
- Launch Templates define compute
- ALB distributes traffic
- ASG manages instance count
- CloudWatch triggers scaling actions
The biggest lesson was understanding how Terraform modules can model real infrastructure relationships while keeping the code reusable and organized.
This project felt like the first truly production-style deployment in the challenge, combining modularity, scalability, automation, and resilience into one infrastructure workflow.
Day 26 showed how Infrastructure as Code moves beyond provisioning resources into designing systems that can adapt automatically to real demand.
Top comments (0)