Deploying a Scalable Kids’ Math App on AWS ECS Fargate: A Complete Terraform Guide

Have you ever wanted to deploy a production-grade application that can handle thousands of kids taking math tests simultaneously without breaking a sweat? Today, we’re diving into exactly how to do that using Terraform, AWS ECS Fargate, and Docker. Say hello to the math-test-app—a Node.js-based math testing platform built for scale and reliability.

The Challenge

Building infrastructure manually through the AWS console is tedious, error-prone, and not repeatable. As developers, we want infrastructure as code — where every resource is defined, version-controlled, and reproducible. We also need high availability, auto-scaling, and proper load balancing for an application that kids depend on during test time.

Enter Terraform and AWS ECS Fargate.

What We’re Building

The math-test-app project deploys a fully managed, containerized application with:

  • High availability across multiple availability zones
  • Auto-scaling that grows with demand and shrinks when traffic drops
  • Load balancing to distribute traffic evenly
  • Containerization using Docker (image: muralidockertest/math-test-app:2.0)
  • Infrastructure as Code with Terraform for repeatability

All of this without worrying about managing EC2 instances directly. That’s the beauty of AWS Fargate.

Architecture Overview

1. VPC and Networking

The foundation begins with a Virtual Private Cloud (VPC) configured with CIDR block 10.0.0.0/16. Within this VPC, we create:

  • 2 Public Subnets (10.0.1.0/24 and 10.0.2.0/24) — where the Application Load Balancer lives and can receive internet traffic
  • 2 Private Subnets (10.0.10.0/24 and 10.0.11.0/24) — where ECS tasks run securely, isolated from direct internet access

This separation is crucial for security. Your containers never expose themselves directly to the internet.

2. Load Balancing

The Application Load Balancer (ALB) sits in the public subnets and receives all incoming HTTP traffic on port 80. It then intelligently forwards requests to healthy ECS tasks running on port 3000 in the private subnets.

The target group’s health check ensures that only healthy containers receive traffic. If a task fails to respond to HTTP requests, the ALB stops sending traffic to it.

health_check {
healthy_threshold = 2
unhealthy_threshold = 2
timeout = 3
interval = 30
path = "/"
matcher = "200"
}

This means the ALB pings your app every 30 seconds, and if it gets 2 consecutive failures, that task is marked unhealthy and taken out of rotation.

3. Security Groups

Two security groups work together:

  • ALB Security Group — allows inbound HTTP (port 80) and HTTPS (port 443) from the world
  • ECS Tasks Security Group — allows inbound traffic only on port 3000 from the ALB, nothing else

This creates a fortress-like defense. Traffic can only reach your app through the ALB. Direct access is blocked.

4. NAT Gateways

Here’s a detail many overlook: your containers running in private subnets need to reach the internet for package updates, API calls, or pulling dependencies. That’s where NAT Gateways come in.

Each private subnet routes its outbound traffic through a NAT Gateway in the corresponding public subnet. Your containers get internet access without ever being directly exposed to the internet themselves.

5. ECS Fargate

This is where your app lives. Fargate handles the heavy lifting — you don’t manage EC2 instances, security patches, or cluster scaling. You just define your task, set CPU and memory, and Fargate handles the rest.

For math-test-app, we specify:

  • CPU: 512 units
  • Memory: 1024 MB
  • Desired Count: 2 tasks (one per AZ for high availability)
  • Image: muralidockertest/math-test-app:2.0
  • Port: 3000

6. Auto-Scaling

Here’s where it gets intelligent. The setup includes two auto-scaling policies:

CPU-based Scaling: If average CPU utilization hits 70%, Fargate automatically spins up more tasks (up to a max of 4). When traffic drops and CPU falls below 70%, it scales down.

Memory-based Scaling: Similarly, if memory utilization reaches 80%, new tasks are created.

This means:

  • During peak test times, your app automatically scales to handle the load
  • During off-peak hours, you pay for fewer resources
  • No manual intervention needed

7. Logging

Every task writes logs to CloudWatch, making debugging and monitoring a breeze. The Terraform config sets up a log group with a 7-day retention policy, keeping costs reasonable while giving you enough history to investigate issues.

The Terraform Blueprint

The ecs.tf file defines all of this declaratively. Key variables you can customize:

variable "app_name" {
default = "math-test-app"
}
variable "container_port" {
default = 3000
}variable "container_cpu" {
default = 512 # Options: 256, 512, 1024, 2048, 4096
}variable "container_memory" {
default = 1024 # in MB
}variable "desired_count" {
default = 2
}

Want to test with smaller resources? Change container_cpu to 256 and container_memory to 512. Need more capacity? Bump desired_count to 3. It’s that simple.

Deploying in 3 Steps

  1. Initialize Terraform:
terraform init

2. Review the plan:

terraform plan

3. Apply the configuration:

terraform apply

Once deployed, Terraform outputs the ALB’s DNS name. Paste it in your browser, and boom — your math-test-app is live.

Repo URL : https://github.com/muralikrishna-sunkara/math-test-app

Why This Architecture?

  • Reliability: Multi-AZ deployment means if one availability zone goes down, your app stays live
  • Scalability: Auto-scaling handles traffic spikes automatically
  • Security: Private subnets, security groups, and NAT gateways create multiple layers of protection
  • Cost-efficiency: You only pay for resources you use; Fargate scales down during off-peak hours
  • Simplicity: Fargate removes the operational burden of managing infrastructure

The Bottom Line

This Terraform configuration transforms deploying a web application from a complex, manual process into a simple, repeatable workflow. Whether complex applications, the infrastructure automatically adapts.

The beauty of Infrastructure as Code is that this entire setup is version-controlled, documented, and can be deployed identically across environments. Change the variables, run terraform apply, and you have a new environment ready to go.

For educational platforms like a kids’ math testing app, this level of reliability and scalability isn’t just nice to have — it’s essential. When exam time arrives, you want your infrastructure to just work.

Leave a Reply

Your email address will not be published. Required fields are marked *

Related Post

AWS Regional NAT Gateway: The Game-Changing Update That Simplifies Multi-AZ Networking

A deep dive into AWS’s new Regional NAT Gateway — automatic multi-AZ expansion, simplified architecture, and hands-on Terraform implementation Introduction If you’ve ever managed AWS VPC networking at scale, you know the pain: deploying NAT Gateways across multiple Availability Zones means managing separate gateways, public subnets, route tables, and Elastic IPs for each AZ. It’s […]

🛑 The Troubleshooting Playbook: Resolving Common Kubernetes Node Failures

Kubernetes is the engine of modern cloud infrastructure, but even the best engines sometimes sputter. When a node (the worker machine running your containers) fails, your pods get evicted, and your application availability plummets. Mastering node troubleshooting means quickly identifying the issue behind the cryptic status messages. Here is a playbook covering the most common […]

Hosting a Static DevOps Resources Website on AWS with Terraform: A Complete Guide

Introduction In today’s fast-paced DevOps landscape, having a centralized hub for essential tools and resources can be invaluable. Whether you’re onboarding new team members, sharing best practices, or simply maintaining a quick reference guide for cloud and DevOps tools, a well-organized static website can be the perfect solution. In this post, I’ll walk you through […]