🚀 AWS ECS Infrastructure
Complete Tutorial Guide – From Beginner to Advanced
📚 AWS ECS Tutorial Overview
This section covers the concepts, services, and components you’ll be working with. Read through this section first to understand what each resource does before you start building.
Best for: Beginners who want to understand AWS ECS infrastructure before implementation
Architecture Overview
Public Subnets (AZ-A, AZ-B)
Private Subnets (Port 80)
Private Subnets (Port 3001)
Private Subnets (Port 5432)
Traffic Flow
- Inbound: Internet → ALB → ECS Tasks (Frontend/Backend)
- Outbound: ECS Tasks → NAT Gateway → Internet (for pulling images, API calls)
- Internal: ECS Tasks → RDS Database (via Security Groups)

Virtual Private Cloud (VPC)




📖 Understanding VPC
A Virtual Private Cloud (VPC) is your own isolated network environment within AWS. Think of it as your private data center in the cloud where you have complete control over:
- IP Address Ranges: Define your own CIDR blocks (e.g., 10.0.0.0/16)
- Subnets: Divide your network into public (internet-facing) and private (internal) subnets
- Routing: Control how traffic flows between subnets and to the internet
- Security: Implement network-level security with security groups and network ACLs
Without a VPC, your resources would be exposed to the public internet with no network isolation. The VPC keeps your ECS tasks, RDS database, and load balancer in a protected network, only accessible through controlled entry points.
What Gets Created:
- VPC with DNS hostnames enabled
- Internet Gateway (for public subnets)
- Public Subnets (for ALB and NAT Gateways)
- Private Subnets (for ECS tasks and RDS)
- NAT Gateways (for outbound internet access from private subnets)
- Route Tables (directing traffic appropriately)
Security Groups

📖 Understanding Security Groups
Security Groups act as virtual firewalls that control inbound and outbound traffic for your AWS resources. Here’s what makes them useful:
- Stateful: If you allow inbound traffic, the response is automatically allowed outbound
- Resource-Level: Attached to network interfaces (EC2, RDS, ALB, ECS tasks)
- Rule-Based: Define rules based on protocol, port, and source/destination
- Default Deny: All traffic is denied by default unless explicitly allowed
Security groups are your first line of defense. They ensure only authorized traffic reaches your resources – think of them as bouncers at a club, checking IDs before letting anyone in.
You’ll create three security groups:
- ALB-SG: Allows HTTP/HTTPS from internet (0.0.0.0/0)
- ECS-SG: Allows ports 80 and 3001 from ALB-SG only
- RDS-SG: Allows PostgreSQL (port 5432) from ECS-SG only
IAM Roles



📖 Understanding IAM Roles
IAM (Identity and Access Management) Roles are AWS identities with permission policies that define what actions can be performed. For ECS, you’ll work with two types:
- Task Execution Role: Used by ECS infrastructure to pull Docker images from ECR, write logs to CloudWatch, and read secrets from Parameter Store. This is required – without it, ECS can’t pull your images.
- Task Role: Used by your application code running inside containers to access AWS services (S3, DynamoDB, etc.). This is optional but recommended if your app needs AWS API access.
Roles follow the principle of least privilege – each component only gets the permissions it needs. This keeps your infrastructure secure and makes troubleshooting easier.
You’ll create three roles:
- ecsTaskExecutionRole: For ECS to pull images, write logs, read parameters
- frontendTaskRole: For frontend application (optional CloudWatch permissions)
- backendTaskRole: For backend application (RDS, S3 access if needed)
Elastic Container Registry (ECR)

📖 Understanding ECR
Amazon Elastic Container Registry (ECR) is a fully managed Docker container registry that stores, manages, and deploys Docker container images. It’s integrated with ECS, so pushing images and having ECS pull them is seamless.
Think of ECR as a private Docker Hub for your AWS account. When you build your application, you push the image to ECR, and ECS pulls it automatically when starting tasks. This keeps your images secure and close to where they’re used.
You’ll create two repositories:
- frontend-repo: Stores frontend Docker images
- backend-repo: Stores backend Docker images
RDS PostgreSQL Database
📖 Understanding RDS
Amazon Relational Database Service (RDS) is a managed database service that makes it easy to set up, operate, and scale relational databases in the cloud. Instead of managing database servers yourself, RDS handles:
- Provisioning: Automated database setup
- Backups: Automated daily backups with point-in-time recovery
- Scaling: Easy vertical scaling (instance size) and read replicas
- Maintenance: Automated patching and updates
Your backend application needs a database to store data. RDS provides a managed PostgreSQL database that’s secure, scalable, and reliable – no need to worry about database server management.
Amazon ECS (Elastic Container Service)

📖 Understanding Amazon ECS
Amazon Elastic Container Service (ECS) is a fully managed container orchestration service that makes it easy to deploy, manage, and scale containerized applications on AWS. It’s AWS’s native container orchestration platform, designed specifically for AWS infrastructure.
Core Components:
- Cluster: A logical grouping of tasks or services. Think of it as a container for your containerized applications.
- Task Definition: A blueprint that describes how to run your container (CPU, memory, image, ports, environment variables, etc.)
- Task: A running instance of a task definition. This is your actual containerized application running.
- Service: Maintains a desired number of running tasks simultaneously. Handles load balancing, auto-scaling, and health monitoring.
- Container: A lightweight, portable package containing your application and its dependencies.
Launch Types:
- Fargate (Serverless): No EC2 instances to manage. AWS handles all infrastructure. Pay only for running containers.
- EC2: You manage EC2 instances. More control but more management overhead.
What Makes ECS Powerful:
- Fully Managed: AWS handles infrastructure provisioning, scaling, and patching
- Integrated: Works seamlessly with ALB, CloudWatch, ECR, IAM, and other AWS services
- Scalable: Automatically scales based on demand or manual configuration
- Secure: Built-in security features, IAM integration, VPC networking
- Cost-Effective: Pay only for what you use (Fargate) or optimize EC2 costs
🔄 ECS vs Other AWS Services – Comparison Table
| Service | Use Case | Infrastructure | Scaling | Best For |
|---|---|---|---|---|
| ECS Fargate | Containerized applications | Serverless (AWS managed) | Automatic/Manual | Microservices, web apps, APIs |
| ECS EC2 | Containerized applications | You manage EC2 instances | Automatic/Manual | When you need instance-level control |
| EKS (Kubernetes) | Kubernetes workloads | Managed Kubernetes control plane | Kubernetes autoscaling | Complex orchestration, multi-cloud |
| Lambda | Event-driven functions | Fully serverless | Automatic (per request) | Short-lived functions, event processing |
| EC2 | Traditional applications | You manage everything | Manual | Legacy apps, full control needed |
| App Runner | Containerized web apps | Fully managed | Automatic | Simple deployments, CI/CD built-in |
🎯 When to Use ECS?
Use ECS Fargate when:
- ✅ You want to run containerized applications without managing servers
- ✅ You need automatic scaling and load balancing
- ✅ You want to focus on application code, not infrastructure
- ✅ You need high availability and fault tolerance
- ✅ You want seamless integration with other AWS services
- ✅ You’re building microservices architectures
- ✅ You need to run long-running applications (not just functions)
- ✅ You want predictable pricing based on CPU/memory
Don’t use ECS when:
- ❌ You need sub-second cold starts (use Lambda instead)
- ❌ You need Kubernetes-specific features (use EKS instead)
- ❌ You’re running very simple, single-container apps (consider App Runner)
- ❌ You need instance-level OS access and customization (use EC2)
- ❌ Your workload is purely event-driven with no long-running processes (consider Lambda)
🚀 Deployment Strategies in ECS
ECS supports multiple deployment strategies to ensure zero-downtime updates:
1. Rolling Update (Default)
- How it works: Gradually replaces old tasks with new ones
- Process: Starts new tasks → Waits for health checks → Shifts traffic → Stops old tasks
- Configuration: Minimum healthy percent: 100%, Maximum percent: 200%
- Best for: Most applications, standard deployments
- Downtime: Zero downtime if configured correctly
2. Blue/Green Deployment
- How it works: Creates a completely new set of tasks alongside old ones
- Process: Deploy new version → Test thoroughly → Switch traffic → Keep old version for rollback
- Configuration: Use separate services or task definitions
- Best for: Critical applications, when you need instant rollback
- Downtime: Zero downtime
3. Canary Deployment
- How it works: Gradually shifts traffic from old to new version
- Process: Deploy new version → Route 10% traffic → Monitor → Gradually increase to 100%
- Configuration: Use ALB weighted target groups or separate services
- Best for: Testing new versions with real traffic, risk reduction
- Downtime: Zero downtime
4. Circuit Breaker Pattern
- How it works: Automatically rolls back if deployment fails
- Process: Deploy → Monitor health checks → Auto-rollback on failure
- Configuration: Enable deployment circuit breaker in service
- Best for: Automated safety, preventing bad deployments
- Downtime: Prevents downtime from bad deployments
🔒 Security Considerations in ECS
ECS provides multiple layers of security:
1. Network Security
- VPC Isolation: Run tasks in private subnets, isolated from internet
- Security Groups: Control inbound/outbound traffic at task level
- Network ACLs: Additional layer of network security (optional)
- No Public IPs: Tasks in private subnets don’t need public IPs
2. IAM Security
- Task Execution Role: Minimal permissions for ECS to pull images, write logs
- Task Role: Application-level permissions (principle of least privilege)
- Service-Linked Roles: For ECS service operations
- No Hardcoded Credentials: Use IAM roles, not access keys
3. Container Security
- Image Scanning: ECR automatically scans images for vulnerabilities
- Secrets Management: Use Parameter Store or Secrets Manager (not environment variables)
- Least Privilege: Run containers with minimal required permissions
- Image Source: Only pull images from trusted registries (ECR)
4. Runtime Security
- Logging: All container logs go to CloudWatch (audit trail)
- Monitoring: CloudWatch metrics for security events
- Encryption: Encrypt data in transit (TLS) and at rest (EBS encryption)
- Compliance: ECS supports HIPAA, PCI-DSS, SOC compliance
5. Best Practices
- ✅ Use private subnets for tasks
- ✅ Enable VPC Flow Logs for network monitoring
- ✅ Regularly update container images with security patches
- ✅ Use secrets management (Parameter Store/Secrets Manager)
- ✅ Enable CloudTrail for API call auditing
- ✅ Implement least privilege IAM policies
- ✅ Use ECR image scanning
- ✅ Enable encryption for EBS volumes
❓ Technical Q&A – Common ECS Questions
Q1: What’s the difference between ECS Fargate and ECS EC2?
A: Fargate is serverless – AWS manages all infrastructure. EC2 requires you to manage EC2 instances. Fargate is simpler but EC2 gives more control and can be more cost-effective at scale.
Q2: How does ECS handle container failures?
A: ECS automatically restarts failed containers. Services monitor task health and replace unhealthy tasks. Health checks ensure only healthy tasks receive traffic.
Q3: Can I run multiple containers in one task?
A: Yes! A task definition can define multiple containers that share networking and storage. They’re always scheduled together on the same infrastructure.
Q4: How does ECS scale applications?
A: ECS can scale based on CloudWatch metrics (CPU, memory, request count). You configure target tracking policies, and ECS automatically adjusts the number of tasks.
Q5: What happens during a deployment?
A: ECS starts new tasks with the updated image, waits for them to pass health checks, gradually shifts traffic from old to new tasks, then stops old tasks. This ensures zero downtime.
Q6: How do containers communicate with each other?
A: Containers in the same task share networking and can communicate via localhost. Containers in different tasks communicate via service discovery (DNS names) or through the load balancer.
Q7: Can I use ECS with Kubernetes?
A: No, ECS is AWS’s own orchestration platform. If you need Kubernetes, use EKS (Elastic Kubernetes Service). However, both can coexist in the same AWS account.
Q8: How much does ECS cost?
A: ECS itself is free. You pay for:
- Fargate: CPU and memory resources used
- EC2: EC2 instance costs
- ALB: Load balancer hours and data transfer
- ECR: Storage for container images
- CloudWatch: Logs and metrics
Q9: Can I run stateful applications on ECS?
A: Yes, but it’s not recommended. ECS is designed for stateless applications. For stateful apps, use EBS volumes for persistent storage, or better yet, use managed services like RDS for databases.
Q10: How do I update my application without downtime?
A: Use rolling updates with proper configuration (minimum healthy percent: 100%, maximum percent: 200%). ECS will start new tasks, wait for health checks, shift traffic, then stop old tasks automatically.
Q11: What’s the difference between a task and a service?
A: A task is a single running container instance. A service maintains a desired number of tasks, handles load balancing, auto-scaling, and ensures tasks are always running.
Q12: Can I use Docker Compose with ECS?
A: Yes! AWS provides ECS Compose CLI that converts Docker Compose files to ECS task definitions. However, native ECS task definitions offer more AWS-specific features.
Q13: How do I handle secrets in ECS?
A: Use AWS Systems Manager Parameter Store or Secrets Manager. Reference secrets in task definitions, and ECS will inject them as environment variables at runtime. Never hardcode secrets!
Q14: What happens if a task runs out of memory?
A: ECS will stop the task and start a new one. The service will maintain the desired count. Monitor CloudWatch metrics to adjust memory allocation in task definitions.
Q15: Can I run Windows containers on ECS?
A: Yes, ECS supports both Linux and Windows containers. However, Windows containers require EC2 launch type (not Fargate) and Windows EC2 instances.
✅ Key Takeaways
- ECS is AWS’s native container orchestration platform
- Fargate provides serverless containers – no infrastructure management
- Great for microservices, web applications, and APIs
- Supports multiple deployment strategies for zero-downtime updates
- Built-in security features with VPC, IAM, and encryption
- Integrates seamlessly with other AWS services
ECS Services

📖 Understanding ECS Services
ECS Service runs and maintains a specified number of instances of a task definition simultaneously. It’s the component that keeps your application running.
What services handle:
- Desired Count: Maintains specified number of running tasks
- Load Balancing: Integrates with ALB to distribute traffic
- Auto Scaling: Can scale based on demand
- Rolling Updates: Zero-downtime deployments
Services ensure your application is always running. If a task crashes, the service automatically starts a new one – you don’t have to babysit it.
ECS Task Definitions
📖 Understanding Task Definitions
ECS Task Definition is a blueprint for your application. It describes everything ECS needs to know to run your containers:
- Container Images: Which Docker images to use
- Resources: CPU and memory allocation
- Ports: Which ports to expose
- Environment Variables: Configuration values
- Secrets: Secure values from Parameter Store
- Logging: Where to send container logs
Task definitions tell ECS exactly how to run your containers. You create the definition once, and ECS uses it to launch tasks. Think of it as a recipe – follow it, and you get the same result every time.
📦 Example: Frontend Task Definition (High-Level)
This is a simplified view of what your frontend-task definition looks like in JSON form. It shows the most important parts you’ll care about:
How to read this:
- family: Logical name of the task definition (
frontend-task) - containerDefinitions: List of containers that run together (here only
frontend) - image: Points to the Docker image in ECR (updated by CI/CD)
- portMappings: Exposes port
80from the container to the load balancer - environment: Plain configuration values (non-secret)
- logConfiguration: Sends logs to CloudWatch Logs group
/ecs/frontend
This example matches what you’ll actually create in Tab 2 (Step 9: Create ECS Task Definitions), but here it’s shown in a simplified, conceptual way.
Application Load Balancer (ALB)

📖 Understanding Application Load Balancer
Application Load Balancer (ALB) is a Layer 7 (application layer) load balancer that distributes incoming HTTP/HTTPS traffic across multiple targets (your ECS tasks) in multiple Availability Zones.
What ALB does:
- Layer 7 Routing: Routes based on HTTP/HTTPS content (URL path, host header)
- Path-Based Routing: Routes
/api/*to backend,/to frontend - Health Checks: Continuously monitors target health
- High Availability: Automatically distributes across multiple AZs
How ALB Works:
- User requests come to ALB DNS name
- ALB examines the request path
- If path starts with
/api/*, routes to backend target group - If path is anything else, routes to frontend target group
- ALB performs health checks on targets
- Only healthy targets receive traffic
CloudWatch Log Groups
📖 Understanding CloudWatch Logs
Amazon CloudWatch Logs is a service for monitoring, storing, and accessing log files from AWS resources and applications.
You need to see what’s happening in your containers. CloudWatch Logs provides visibility into application behavior, errors, and performance – essential for debugging and monitoring.
You’ll create two log groups:
/ecs/frontend– Frontend application logs/ecs/backend– Backend application logs
Systems Manager Parameter Store

📖 Understanding Parameter Store
AWS Systems Manager Parameter Store provides secure, hierarchical storage for configuration data and secrets.
Store database credentials, API URLs, and other configuration securely here. ECS tasks can access these values without hardcoding secrets in your code – much safer than putting passwords in environment variables or code.
Two types of parameters:
- String: Plain text values (e.g., URLs, ports)
- SecureString: Encrypted values (e.g., passwords, API keys)
✅ You’ve Learned the Basics!
Now that you understand what each resource does, proceed to Tab 2: Step-by-Step Setup to learn how to create them.
💡 Pro Tip: Bookmark this page – you’ll want to reference these concepts as you build. Understanding the “why” makes troubleshooting much easier later.
📋 CI/CD Overview
This section covers setting up automated deployment using GitHub Actions. Once configured, every push to your main branch will automatically build Docker images, push them to ECR, and update your ECS services.
Prerequisites: All infrastructure resources from Steps 1-11 must be completed.
📦 Application Repositories
You need to set up CI/CD for both repositories:
- Frontend Repository: https://github.com/m-saad-siddique/frontend
- Backend Repository: https://github.com/m-saad-siddique/backend
Note: Each repository requires its own GitHub Actions workflow file and secrets configuration. The workflow process is the same for both, but with different repository names, ECR repositories, and ECS services.
CI/CD Pipeline Architecture
Code Push
Build & Deploy
Push Image
Update & Deploy


GitHub Actions CI/CD Setup
📖 Understanding GitHub Actions
GitHub Actions is a CI/CD platform that automates your software workflows. When you push code to GitHub, Actions can:
- Build: Compile your application and create Docker images
- Test: Run automated tests
- Deploy: Push images to ECR and update ECS services
Manual deployments are error-prone and time-consuming. CI/CD ensures consistent, automated deployments every time you push code – no more “it works on my machine” issues.
Step 1: Configure GitHub Secrets
Navigate to Repository Settings
- Go to your GitHub repository
- Click “Settings” tab
- Click “Secrets and variables” → “Actions”
Create AWS Credentials Secret
Click “New repository secret” and add:
- Name:
AWS_ACCESS_KEY_ID - Value: Your AWS access key ID
- Click “Add secret”
Add Remaining AWS Secrets
Add these AWS credential secrets (one at a time):
| Secret Name | Description |
|---|---|
AWS_SECRET_ACCESS_KEY | Your AWS secret access key |
AWS_REGION | e.g., us-east-1 |
ECR_REPOSITORY, ECS_SERVICE, or ECS_CLUSTER as secrets. These values are hardcoded in the workflow file’s env section, which is the recommended approach.🔄 How the GitHub Actions Workflow Works
The CI/CD pipeline automates the entire deployment process. Here’s how it works step by step:
- Trigger: When you push code to the
mainbranch, GitHub Actions automatically detects the change and starts the workflow. - Checkout Code: The workflow checks out your repository code to the GitHub Actions runner (a virtual machine).
- Configure AWS Credentials: Uses the AWS credentials stored in GitHub Secrets to authenticate with your AWS account.
- Login to ECR: Authenticates Docker with Amazon ECR so it can push images.
- Build Docker Image: Builds your application into a Docker image using the Dockerfile in your repository.
- Tag Image: Tags the image with the Git commit SHA (unique identifier) for version tracking.
- Push to ECR: Uploads the Docker image to your ECR repository.
- Download Task Definition: Retrieves the current ECS task definition from AWS.
- Update Task Definition: Updates the task definition with the new image URI (points to the newly pushed image).
- Deploy to ECS: Updates the ECS service with the new task definition, triggering a rolling deployment.
- Wait for Stability: Waits for the new tasks to become healthy before completing.
Rolling Deployment Process:
- ECS starts new tasks with the updated image
- New tasks register with the target group and pass health checks
- ALB gradually shifts traffic from old tasks to new tasks
- Old tasks are stopped once new tasks are healthy
- This ensures zero-downtime deployments
For Frontend Repository: The workflow builds the Next.js application, pushes to frontend-repo in ECR, and updates frontend-service in ECS.
For Backend Repository: The workflow builds the Node.js/TypeScript backend, pushes to backend-repo in ECR, and updates backend-service in ECS.
Step 2: Create GitHub Actions Workflow
Create Workflow Directory
- In your repository root, create:
.github/workflows/ - Create file:
.github/workflows/deploy.yml
Frontend Workflow Example
For the Frontend Repository (github.com/m-saad-siddique/frontend), add this content to deploy.yml:
Backend Workflow
For the Backend Repository (github.com/m-saad-siddique/backend), use the same workflow structure but update these environment variables:
| Environment Variable | Frontend Value | Backend Value |
|---|---|---|
ECR_REPOSITORY | frontend-repo | backend-repo |
ECS_SERVICE | frontend-service | backend-service |
ECS_TASK_DEFINITION | frontend-task | backend-task |
CONTAINER_NAME | frontend | backend-app |
name: Deploy Frontend to ECS to name: Deploy Backend to ECS for clarity.Create Task Definition File
- Create
task-definition.jsonin repository root - Copy the task definition JSON from ECS Console
- GitHub Actions will update the image URI automatically
Step 3: Test the Pipeline
Commit and Push
- Commit the workflow file and task definition
- Push to
mainbranch
Monitor Deployment
- Go to GitHub → “Actions” tab
- Watch the workflow run
- Check ECS Console to see service updating
📋 Workflow Execution Summary
When you push code to the Frontend Repository:
- GitHub Actions triggers the workflow
- Builds Next.js frontend application into Docker image
- Tags image with commit SHA (e.g.,
frontend-repo:abc123) - Pushes image to
frontend-repoin ECR - Downloads current
frontend-tasktask definition - Updates task definition with new image URI
- Deploys updated task definition to
frontend-service - ECS performs rolling update (starts new tasks, shifts traffic, stops old tasks)
- New frontend version is live on ALB
When you push code to the Backend Repository:
- GitHub Actions triggers the workflow
- Builds Node.js/TypeScript backend application into Docker image
- Tags image with commit SHA (e.g.,
backend-repo:xyz789) - Pushes image to
backend-repoin ECR - Downloads current
backend-tasktask definition - Updates task definition with new image URI
- Deploys updated task definition to
backend-service - ECS performs rolling update (starts new tasks, shifts traffic, stops old tasks)
- New backend version is live and accessible via
/api/*routes
✅ CI/CD Setup Complete!
Your pipeline is now configured. Every push to main will automatically:
- Build your Docker image
- Push to ECR
- Update ECS service with new image
- Perform rolling deployment
Next Steps:
- Push code to
mainbranch in either repository - Monitor the deployment in GitHub Actions tab
- Verify the new version is running in ECS Console
- Test your application via the ALB DNS name
🛠️ Implementation Guide
This section provides detailed, step-by-step instructions for creating each AWS resource. Follow these steps in order – each resource depends on previously created resources.
Prerequisites: Make sure you’ve read Tab 1 to understand what each resource does.
Estimated Time: 2-3 hours for complete setup
🚀 Automated Provisioning with Scripts
Prefer automated provisioning? Instead of manually creating resources through the AWS Console, you can use our automated bash scripts to provision all infrastructure resources.
📦 Public Repository: The complete set of provisioning scripts is available in our public GitHub repository:
🔗 https://github.com/m-saad-siddique/ecs-resource-provision-scripts
📁 Local Scripts Directory: If you want to provision this infrastructure using scripts, use the scripts/ directory in this project. The scripts directory contains:
- Step-by-step bash scripts that provision all resources using AWS CLI
- Configuration file (
config.sh) for customizing your deployment - Deploy-all script to run all provisioning steps in sequence
- Individual scripts for each resource (VPC, IAM, ECR, RDS, ECS, ALB, etc.)
💡 Quick Start with Scripts:
- Navigate to the
scripts/directory in this project - Configure
config.shwith your AWS profile, region, and project settings - Run
./deploy-all.shto provision all resources automatically - Or run individual scripts in order (01-networking.sh, 02-iam-roles.sh, etc.)
📖 For detailed script documentation: See the README.md file in the scripts/ directory for complete instructions, prerequisites, and troubleshooting.
Note: The manual step-by-step instructions below are still available if you prefer to create resources through the AWS Console. Choose the method that works best for you!
📝 Quick Reference
Each resource below includes detailed step-by-step instructions. Click on each resource card to see the complete implementation guide.
Implementation Steps (In Order)
✅ Setup Checklist
Complete these resources in order:
📖 Detailed Instructions
The detailed step-by-step instructions for creating each resource are available in the original documentation. Each resource includes:
- Navigation steps (where to click in AWS Console)
- Configuration details (what values to enter)
- Verification steps (how to confirm it’s working)
- Important notes and warnings
Note: All the detailed implementation steps from the original guide are still available. Refer to Tab 1 for understanding what each resource does, then follow the detailed steps in your AWS Console.
Virtual Private Cloud (VPC)




📖 Understanding VPC
A Virtual Private Cloud (VPC) is your own isolated network environment within AWS. Think of it as your private data center in the cloud where you have complete control over:
- IP Address Ranges: Define your own CIDR blocks (e.g., 10.0.0.0/16)
- Subnets: Divide your network into public (internet-facing) and private (internal) subnets
- Routing: Control how traffic flows between subnets and to the internet
- Security: Implement network-level security with security groups and network ACLs
VPC provides network isolation and security. Your ECS tasks, RDS database, and load balancer all run within this isolated network, protected from the public internet except through controlled entry points.
How to Create It:
Navigate to VPC Console
- Log in to AWS Management Console
- Search for “VPC” in the top search bar
- Click on “VPC” service
Create VPC
- Click “Create VPC” button (orange button, top right)
- Select “VPC and more” option
- Fill in the configuration:
Name tag: ecs-production-vpc
IPv4 CIDR block: 10.0.0.0/16
IPv6 CIDR block: No IPv6 (unchecked)
Tenancy: Default
Number of Availability Zones: 2
Number of public subnets: 2
Number of private subnets: 2
NAT gateways: 1 per AZ (creates 2 NAT gateways)
VPC endpoints: None (default)
- Click “Create VPC”
- Wait 2-3 minutes for creation
Verify DNS Settings
- Click on your VPC name to view details
- Go to “Actions” → “Edit VPC settings”
- Ensure “DNS hostnames” is Enabled
- Click “Save changes”
Document Important Information
Write down these values (you’ll need them later):
- VPC ID: e.g.,
vpc-0123456789abcdef0 - Public Subnet IDs: Two subnet IDs (one per AZ)
- Private Subnet IDs: Two subnet IDs (one per AZ)
- Internet Gateway ID: e.g.,
igw-0123456789abcdef0 - NAT Gateway IDs: Two NAT gateway IDs
- VPC with DNS hostnames enabled
- Internet Gateway (attached to VPC)
- 2 Public subnets (one per availability zone)
- 2 Private subnets (one per availability zone)
- 2 NAT Gateways (one in each public subnet)
- Route tables (public routes to IGW, private routes to NAT)
Security Groups

📖 What are Security Groups?
Security Groups act as virtual firewalls that control inbound and outbound traffic for your AWS resources. Key characteristics:
- Stateful: If you allow inbound traffic, the response is automatically allowed outbound
- Resource-Level: Attached to network interfaces (EC2, RDS, ALB, ECS tasks)
- Rule-Based: Define rules based on protocol, port, and source/destination
- Default Deny: All traffic is denied by default unless explicitly allowed
Security groups provide the first line of defense, ensuring only authorized traffic reaches your resources. You’ll create three security groups:
- ALB-SG: Allows HTTP/HTTPS from internet to load balancer
- ECS-SG: Allows traffic from ALB to ECS tasks (ports 80, 3001)
- RDS-SG: Allows PostgreSQL traffic from ECS tasks only
Create ALB Security Group:
Navigate to Security Groups
- In VPC Console, click “Security Groups” in left sidebar
- Click “Create security group”
Configure Basic Settings
- Security group name:
ALB-SG - Description:
Security group for Application Load Balancer - VPC: Select
ecs-production-vpc
Add Inbound Rules
Click “Add rule” twice to add:
- Rule 1:
- Type:
HTTP - Source:
0.0.0.0/0 - Description:
Allow HTTP from internet
- Type:
- Rule 2:
- Type:
HTTPS - Source:
0.0.0.0/0 - Description:
Allow HTTPS from internet
- Type:
Leave outbound rules as default (allows all)
Create and Document
- Click “Create security group”
- Note down the Security Group ID (e.g.,
sg-0123456789abcdef0)
Create ECS Security Group:
Create New Security Group
- Click “Create security group” again
- Name:
ECS-SG - Description:
Security group for ECS tasks - VPC: Select your VPC
Add Inbound Rules
Add two rules (click “Add rule” for each):
- Rule 1 – Port 80:
- Type:
Custom TCP - Port range:
80 - Source: Select “Custom” → Choose
ALB-SGsecurity group - Description:
Allow port 80 from ALB
- Type:
- Rule 2 – Port 3001:
- Type:
Custom TCP - Port range:
3001 - Source: Select “Custom” → Choose
ALB-SGsecurity group - Description:
Allow port 3001 from ALB
- Type:
Click “Create security group” and note the Security Group ID
Create RDS Security Group:
Create Security Group
- Click “Create security group”
- Name:
RDS-SG - Description:
Security group for RDS database - VPC: Select your VPC
Add Inbound Rule
- Click “Add rule”
- Type:
PostgreSQL(or Custom TCP) - Port range:
5432 - Source: Select “Custom” → Choose
ECS-SGsecurity group - Description:
Allow PostgreSQL from ECS tasks
Click “Create security group” and note the Security Group ID
IAM Roles



📖 Understanding IAM Roles
IAM (Identity and Access Management) Roles are AWS identities with permission policies that define what actions can be performed. For ECS, you’ll work with two types:
- Task Execution Role: Used by ECS infrastructure to pull Docker images from ECR, write logs to CloudWatch, and read secrets from Parameter Store. This is required – without it, ECS can’t pull your images.
- Task Role: Used by your application code running inside containers to access AWS services (S3, DynamoDB, etc.). This is optional but recommended if your app needs AWS API access.
Roles follow the principle of least privilege – each component only gets the permissions it needs. The execution role handles infrastructure tasks, while the task role handles application-level AWS API calls.
Create ECS Task Execution Role:
Navigate to IAM
- Search for “IAM” in AWS Console
- Click “Roles” in left sidebar
- Click “Create role”
Select Trusted Entity
- Select “AWS service”
- Under “Use case”, select “Elastic Container Service”
- Select “Elastic Container Service Task”
- Click “Next”
Attach Permissions
- Search for and select:
AmazonECSTaskExecutionRolePolicy - This provides permissions for:
- Pulling images from ECR
- Writing logs to CloudWatch
- Basic Parameter Store access
- Click “Next”
Name the Role
- Role name:
ecsTaskExecutionRole - Description:
Role for ECS task execution - allows pulling images, writing logs, reading parameters - Click “Create role”
Add Parameter Store Permissions
- Click on the role name
ecsTaskExecutionRole - Click “Add permissions” → “Create inline policy”
- Click “JSON” tab
- Paste this policy:
- Click “Next”
- Policy name:
ParameterStoreAccess - Click “Create policy”
Create Frontend Task Role:
Create Role
- Go to IAM → Roles → “Create role”
- Select “AWS service” → “Elastic Container Service” → “Elastic Container Service Task”
- Click “Next” (no permissions needed here)
- Role name:
frontendTaskRole - Description:
Task role for frontend application - Click “Create role”
Create Backend Task Role:
Create Role
- Click “Create role” again
- Same process: “AWS service” → “Elastic Container Service” → “Elastic Container Service Task”
- Role name:
backendTaskRole - Description:
Task role for backend application - Click “Create role”
Elastic Container Registry (ECR)

📖 Understanding ECR
Amazon Elastic Container Registry (ECR) is a fully managed Docker container registry that stores, manages, and deploys Docker container images. It’s integrated with ECS, so pushing images and having ECS pull them is seamless.
Think of ECR as a private Docker Hub for your AWS account. When you build your application, you push the image to ECR, and ECS pulls it automatically when starting tasks. This keeps your images secure and close to where they’re used.
Create Frontend Repository:
Navigate to ECR
- Search for “ECR” in AWS Console
- Click “Repositories” → “Create repository”
Configure Repository
- Visibility: Private
- Repository name:
frontend-repo - Tag immutability: Mutable
- Scan on push: Enable (for security scanning)
- Click “Create repository”
Configure Lifecycle Policy
- Click “Lifecycle policy” tab
- Click “Create lifecycle policy”
- Select “Keep last 10 images”
- Click “Create policy”
Note Repository URI
Copy the repository URI (e.g., 123456789012.dkr.ecr.us-east-1.amazonaws.com/frontend-repo)
Create Backend Repository:
Repeat the same process for backend-repo
- Name:
backend-repo - Enable scan on push
- Create lifecycle policy (keep last 10)
- Note the URI
RDS PostgreSQL Database
📖 Understanding RDS
Amazon Relational Database Service (RDS) is a managed database service that makes it easy to set up, operate, and scale relational databases in the cloud. Instead of managing database servers yourself, RDS handles:
- Provisioning: Automated database setup
- Backups: Automated daily backups with point-in-time recovery
- Scaling: Easy vertical scaling (instance size) and read replicas
- Maintenance: Automated patching and updates
- Monitoring: CloudWatch integration for metrics
Your backend application needs a database to store data. RDS provides a managed PostgreSQL database that’s secure, scalable, and reliable – no need to worry about database server management.
Step 1: Create DB Subnet Group
Navigate to RDS
- Search for “RDS” in AWS Console
- Click “Subnet groups” in left sidebar
- Click “Create DB subnet group”
Configure Subnet Group
- Name:
ecs-db-subnet-group - Description:
Subnet group for ECS RDS database - VPC: Select
ecs-production-vpc - Availability Zones: Select both AZs (us-east-1a, us-east-1b)
- Subnets: Select both PRIVATE subnets (one from each AZ)
Click “Create” button
Step 2: Create PostgreSQL Database
Start Database Creation
- Click “Databases” in left sidebar
- Click “Create database”
Engine Configuration
- Engine type: PostgreSQL
- Version: Latest stable (e.g., PostgreSQL 15.x)
- Templates: Production (or Free tier for testing)
Settings
- DB instance identifier:
ecs-postgres-db - Master username:
postgres - Master password: Create a strong password (save securely!)
- Confirm password: Re-enter password
Instance Configuration
- DB instance class:
db.t3.medium(or db.t3.micro/small for testing)
Storage
- Storage type: General Purpose SSD (gp3)
- Allocated storage:
20GB (minimum) - Storage autoscaling: Enable (optional)
Connectivity
- VPC: Select your VPC
- DB subnet group:
ecs-db-subnet-group - Public access: No (critical!)
- VPC security group: Choose existing → Select
RDS-SG
Database Options
- Initial database name:
fileanalyzer
Backup & Maintenance
- Enable automated backups: Yes (recommended)
- Backup retention period:
7days - Enable auto minor version upgrade: Yes
Click “Create database” and wait 5-10 minutes
Document Database Endpoint
Once status is “Available”, click on database name and note:
- Endpoint: e.g.,
ecs-postgres-db.xxxxx.us-east-1.rds.amazonaws.com - Port:
5432
You’ll need these for Parameter Store.
ECS Cluster

📖 Understanding ECS Clusters
Amazon ECS Cluster is a logical grouping of tasks or services. Think of it as a container for your containerized applications. For AWS Fargate:
- No Infrastructure Management: AWS manages all servers, containers, and networking – you just define what to run
- Namespace: Groups your services and tasks together in one logical unit
- Serverless: No EC2 instances to manage – Fargate handles everything
- Scaling: Automatically handles scaling based on demand and service configuration
- Integration: Works seamlessly with ALB, CloudWatch, ECR, Parameter Store, and other AWS services
- Multi-Service Support: Can run multiple services (frontend, backend) in the same cluster
The cluster is where your ECS services run. It provides the platform for running your containerized applications. Without a cluster, you cannot run ECS services or tasks – think of it as the foundation.
Important concepts:
- Cluster: The container that holds your services
- Service: Maintains a desired number of running tasks (e.g., frontend-service, backend-service)
- Task: A running instance of a task definition (your containerized application)
- Task Definition: Blueprint that describes how to run your container (CPU, memory, image, environment variables)
🔄 ECS Creation Flow
The ECS setup process follows this order:
- Create Cluster (this step) – Sets up the container platform
- Create Task Definitions – Define how containers should run
- Create Services – Run and maintain tasks based on task definitions
- Services connect to ALB – Traffic flows from ALB to services
Note: You’ll create the cluster now, but you’ll need task definitions and services created later (Steps 9 and 11).
How to Create It:
Navigate to ECS Console
- Log in to AWS Management Console
- In the top search bar, type “ECS”
- Click on “Elastic Container Service” from the services list
- You’ll be taken to the ECS Dashboard
Access Clusters Section
- In the left navigation menu, click “Clusters”
- You’ll see a list of existing clusters (if any) or an empty state
- Click the orange “Create cluster” button (top right)
Configure Cluster Settings
You’ll see a form with several sections. Fill in the following:
Cluster configuration:
Cluster name: ecs-production-cluster
Infrastructure:
• Select “AWS Fargate (Serverless)” radio button
• This means AWS manages all infrastructure – no EC2 instances to manage
Monitoring:
• CloudWatch Container Insights: Leave unchecked (optional, adds cost)
• You can enable this later if you need advanced monitoring
Review and Create
- Review your cluster configuration
- Click the orange “Create” button at the bottom
- A success message will appear: “Cluster created successfully”
Verify Cluster Creation
- You’ll be redirected to the cluster details page
- Cluster status should show “Active”
- Note the cluster name:
ecs-production-cluster - You’ll see tabs for: Services, Tasks, Metrics, Logs, etc.
- The cluster itself doesn’t cost anything – you only pay for running tasks
- You can create multiple services in the same cluster (frontend and backend share the same cluster)
- Cluster settings can be modified later if needed
- Double-check you’re in the correct AWS region (top right corner) – resources are region-specific
Application Load Balancer (ALB)

📖 Understanding Application Load Balancer
Application Load Balancer (ALB) is a Layer 7 (application layer) load balancer that distributes incoming HTTP/HTTPS traffic across multiple targets (your ECS tasks) in multiple Availability Zones. Think of it as a smart traffic director.
What ALB does:
- Layer 7 Routing: Routes based on HTTP/HTTPS content (URL path, host header, HTTP headers) – not just IP addresses
- Path-Based Routing: Routes
/api/*to backend service,/to frontend service - Health Checks: Continuously monitors target health and routes only to healthy targets
- SSL Termination: Handles SSL/TLS certificates – decrypts HTTPS traffic
- High Availability: Automatically distributes across multiple Availability Zones
- Auto Scaling: Automatically scales to handle traffic increases
- Sticky Sessions: Can maintain session affinity (optional)
The ALB gives you a single entry point (one DNS name) for your entire application. It distributes requests across multiple ECS tasks for better performance, and if one task fails, traffic automatically routes to healthy tasks. This enables zero-downtime deployments and path-based routing (API calls to backend, web pages to frontend).
How ALB Works:
- User requests come to ALB DNS name (e.g.,
ecs-alb-xxx.elb.amazonaws.com) - ALB examines the request path
- If path starts with
/api/*, routes to backend target group - If path is anything else, routes to frontend target group
- ALB performs health checks on targets
- Only healthy targets receive traffic
🔄 ALB Creation Flow
The ALB setup process follows this order:
- Create ALB – Set up the load balancer infrastructure
- Create Target Groups – Define where traffic should go (frontend-tg, backend-tg)
- Configure Listeners – Set up HTTP/HTTPS listeners on ports 80/443
- Configure Listener Rules – Set up path-based routing rules
- Connect ECS Services – ECS services register with target groups (done in Step 11)
Important: Target groups are created during ALB creation, but ECS tasks will register with them later when you create ECS services.
- VPC with public subnets must be created (Step 1)
- ALB-SG security group must be created (Step 2)
- ALB must be in public subnets to receive internet traffic
Step 1: Create ALB
Navigate to EC2 Console
- Log in to AWS Management Console
- In the top search bar, type “EC2”
- Click on “EC2” service
- In the left navigation menu, scroll down and click “Load Balancers”
- You’ll see a list of existing load balancers (if any) or an empty state
- Click the orange “Create Load Balancer” button (top right)
Select Load Balancer Type
You’ll see three load balancer types. Select:
- Application Load Balancer (the first option)
- This is the correct type for HTTP/HTTPS traffic routing
- Click the orange “Create” button under Application Load Balancer
Basic Configuration
Fill in the basic settings:
Basic configuration:
Name: ecs-alb
Scheme:
• Select “Internet-facing” radio button
• This allows traffic from the internet
• Internal load balancers are only for VPC-internal traffic
IP address type:
• Select “IPv4” (default)
Network Mapping
Configure where the ALB will be placed:
Network mapping:
VPC: Select your VPC (ecs-production-vpc)
Mappings:
• Check both availability zones (us-east-1a and us-east-1b)
• For each AZ, select the PUBLIC subnet from the dropdown
• Do NOT select private subnets
Security Groups
Configure firewall rules:
- You’ll see a default security group selected
- Click the “X” next to the default security group to remove it
- Click “Add security group”
- Select
ALB-SGfrom the list - This security group allows HTTP (port 80) and HTTPS (port 443) from the internet
Listeners and Routing
Configure how traffic is received and routed:
Listeners:
Protocol: HTTP
Port: 80
Default action:
• Click the dropdown and select “Create target group”
• This will open a new page to create the frontend target group
• This gets configured in the next step
🎯 Understanding Target Groups
A Target Group is a collection of targets (ECS tasks) that receive traffic from the load balancer. Think of it as a group of servers that handle the same type of requests.
Key Points:
- Frontend Target Group: Contains frontend ECS tasks (port 80)
- Backend Target Group: Contains backend ECS tasks (port 3001)
- Health Checks: ALB continuously checks if targets are healthy
- Auto Registration: ECS tasks automatically register with target groups when services are created
Step 2: Create Frontend Target Group
Target Group Configuration
When you clicked “Create target group” in the ALB creation, you should now be on the target group creation page. If not, go to EC2 → Target Groups → Create target group.
Basic configuration:
Target type: Select “IP addresses”
• This is required for Fargate tasks (they don’t use EC2 instances)
• Instance type is for EC2-based ECS tasks
Target group name: frontend-tg
Protocol: HTTP
Port: 80 (matches frontend container port)
VPC: Select your VPC (ecs-production-vpc)
Health Check Configuration
Configure how ALB checks if targets are healthy:
Health checks:
Health check protocol: HTTP
Health check path: /
• ALB will check this path to determine if the target is healthy
• Frontend should return 200 OK for the root path
Advanced health check settings: (Click to expand)
Healthy threshold: 2 consecutive successful checks
Unhealthy threshold: 2 consecutive failed checks
Timeout: 5 seconds (max time to wait for response)
Interval: 30 seconds (time between checks)
Success codes: 200 (default)
Register Targets (Skip for Now)
- Click “Next” button
- On the “Register targets” page, you’ll see an empty list
- Do NOT register targets manually – ECS will automatically register tasks when you create the service
- Click “Next” again to skip this step
Review and Create
- Review your target group configuration
- Click “Create target group” button
- You’ll see a success message
Step 3: Complete ALB Creation
Return to ALB Creation
- Go back to ALB creation page
- Under “Default action”, select
frontend-tg - Click “Create load balancer”
- Wait 2-3 minutes for creation
Step 4: Create Backend Target Group
Create Target Group
- Go to EC2 → “Target Groups” → “Create target group”
- Target type: IP addresses
- Name:
backend-tg - Protocol: HTTP
- Port:
3001 - VPC: Select your VPC
- Health check path:
/api/health
Click “Next” → “Create target group”
Step 5: Configure Listener Rules
Configure Routing Rules
- Go to “Load Balancers” → Click
ecs-alb - Click “Listeners” tab → Click listener (port 80)
- Click “Manage rules”
Add API Route
- Click “Add rule”
- IF (conditions): Click “Add condition” → Select “Path” → Enter
/api/* - THEN (actions): Click “Add action” → “Forward to” → Select
backend-tg - Priority:
100
Click “Save changes”
Verify default rule forwards to frontend-tg
Document ALB DNS Name
In ALB details, under “Basic configuration”, copy the DNS name:
e.g., ecs-alb-123456789.us-east-1.elb.amazonaws.com
You’ll need this for Parameter Store.
✅ ALB Setup Complete!
What You’ve Created:
- ✅ Application Load Balancer (
ecs-alb) in public subnets - ✅ Frontend Target Group (
frontend-tg) for port 80 - ✅ Backend Target Group (
backend-tg) for port 3001 - ✅ Listener on port 80 with routing rules
- ✅ Path-based routing:
/api/*→ backend,/→ frontend
How Traffic Flows:
- User requests
http://ALB-DNS-NAME/→ Routes to frontend-tg → Frontend ECS tasks - User requests
http://ALB-DNS-NAME/api/health→ Routes to backend-tg → Backend ECS tasks - ALB performs health checks on all targets
- Only healthy targets receive traffic
- If a target becomes unhealthy, ALB stops sending traffic to it
Next Steps: Create CloudWatch Log Groups (Step 8), then Task Definitions (Step 9), then connect ECS Services to these target groups (Step 11).
CloudWatch Log Groups
📖 Understanding CloudWatch Logs
Amazon CloudWatch Logs is a service for monitoring, storing, and accessing log files from AWS resources and applications. Here’s what it offers:
- Centralized Logging: All container logs in one place
- Search & Filter: Easy log searching and filtering
- Retention Policies: Automatically delete old logs
- Integration: ECS automatically sends container logs
You need to see what’s happening in your containers. CloudWatch Logs provides visibility into application behavior, errors, and performance – essential for debugging.
Navigate to CloudWatch
- Search for “CloudWatch” in AWS Console
- Click “Log groups” in left sidebar
- Click “Create log group”
Create Frontend Log Group
- Log group name:
/ecs/frontend - Log retention: Select retention period (e.g., 30 days)
- Click “Create”
Create Backend Log Group
- Click “Create log group” again
- Log group name:
/ecs/backend - Log retention: 30 days
- Click “Create”
ECS Task Definitions
📖 Understanding Task Definitions
ECS Task Definition is a blueprint for your application. It describes:
- Container Images: Which Docker images to use
- Resources: CPU and memory allocation
- Ports: Which ports to expose
- Environment Variables: Configuration values
- Secrets: Secure values from Parameter Store
- Logging: Where to send container logs
- IAM Roles: Permissions for the task
Task definitions tell ECS exactly how to run your containers. You create the definition once, and ECS uses it to launch tasks – think of it as a recipe that ECS follows every time.
Create Frontend Task Definition:
Navigate to Task Definitions
- Go to ECS Console → “Task definitions”
- Click “Create new task definition”
Basic Configuration
- Task definition family:
frontend-task - Launch type: Fargate
- Operating system: Linux/X86_64
Task Size
- Task CPU:
0.5 vCPU(512) - Task memory:
1 GB(1024)
IAM Roles
- Task role:
frontendTaskRole - Task execution role:
ecsTaskExecutionRole
Add Container
Scroll down and click “Add container”:
- Container name:
frontend - Image URI: Your ECR URI + tag (e.g.,
123456789012.dkr.ecr.us-east-1.amazonaws.com/frontend-repo:latest) - Essential container: Yes (checked)
Port Mappings
- Click “Add port mapping”
- Container port:
80 - Protocol: TCP
Environment Variables – Secrets
- Under “Environment variables” → “Secrets”
- Click “Add secret”
- Key:
NEXT_PUBLIC_API_URL - Value from: Parameter Store →
/ecs/frontend/API_URL
Logging Configuration
- Under “Logging”:
- Log driver:
awslogs - Log options:
- awslogs-group:
/ecs/frontend - awslogs-region: Your region (e.g.,
us-east-1) - awslogs-stream-prefix:
ecs
- awslogs-group:
Click “Add” → Scroll to bottom → Click “Create”
Create Backend Task Definition:
Create New Task Definition
- Click “Create new task definition”
- Family:
backend-task - Launch type: Fargate
- Task CPU:
1 vCPU(1024) - Task memory:
2 GB(2048) - Task role:
backendTaskRole - Task execution role:
ecsTaskExecutionRole
Add Container
- Click “Add container”
- Container name:
backend-app - Image URI: Backend ECR URI
Port & Environment
- Container port:
3001 - Under “Environment variables” → “Environment”:
- Add:
PORT=3001
Add Secrets from Parameter Store
Under “Secrets”, add these (click “Add secret” for each):
DB_HOST→/ecs/backend/DB_HOSTDB_PORT→/ecs/backend/DB_PORTDB_NAME→/ecs/backend/DB_NAMEDB_USER→/ecs/backend/DB_USER(SecureString)DB_PASSWORD→/ecs/backend/DB_PASSWORD(SecureString)FRONTEND_URL→/ecs/backend/FRONTEND_URL
Logging
- Log driver:
awslogs - awslogs-group:
/ecs/backend - awslogs-region: Your region
- awslogs-stream-prefix:
ecs
Click “Add” → “Create”
Systems Manager Parameter Store

📖 Understanding Parameter Store
AWS Systems Manager Parameter Store provides secure, hierarchical storage for configuration data and secrets. Here’s what it offers:
- Secure Storage: Encrypted storage for sensitive data
- Types: String (plain text) or SecureString (encrypted)
- Integration: ECS automatically injects values as environment variables
- Versioning: Track changes to parameters
- Access Control: IAM-based permissions
Store database credentials, API URLs, and other configuration securely here. ECS tasks can access these values without hardcoding secrets in your code – much safer than putting passwords in environment variables.
Create Backend Parameters:
Navigate to Parameter Store
- Search for “Systems Manager” in AWS Console
- Click “Parameter Store” in left sidebar
- Click “Create parameter”
Create DB_HOST Parameter
- Name:
/ecs/backend/DB_HOST - Description: RDS database endpoint
- Tier: Standard
- Type: String
- Value: Your RDS endpoint (from Step 5)
Click “Create parameter”
Create Remaining Backend Parameters
Create these parameters (one at a time):
| Name | Type | Value |
|---|---|---|
/ecs/backend/DB_PORT | String | 5432 |
/ecs/backend/DB_NAME | String | fileanalyzer |
/ecs/backend/DB_USER | SecureString | Your database username |
/ecs/backend/DB_PASSWORD | SecureString | Your database password |
/ecs/backend/FRONTEND_URL | String | ALB DNS name (e.g., http://ecs-alb-xxx.elb.amazonaws.com) |
Create Frontend Parameters:
Create API_URL Parameter
- Click “Create parameter”
- Name:
/ecs/frontend/API_URL - Type: String
- Value: ALB DNS name +
/api(e.g.,http://ecs-alb-xxx.elb.amazonaws.com/api)
Click “Create parameter”
ECS Services

📖 Understanding ECS Services
ECS Service runs and maintains a specified number of instances of a task definition simultaneously. Here’s what services handle:
- Desired Count: Maintains specified number of running tasks
- Load Balancing: Integrates with ALB to distribute traffic
- Auto Scaling: Can scale based on demand
- Rolling Updates: Zero-downtime deployments
- Health Monitoring: Restarts unhealthy tasks
Services ensure your application is always running. If a task crashes, the service automatically starts a new one. Services handle deployments and scaling – you don’t have to babysit your containers.
Create Frontend Service:
Navigate to Cluster
- Go to ECS → Clusters →
ecs-production-cluster - Click “Services” tab
- Click “Create”
Configure Service
- Launch type: Fargate
- Task definition:
frontend-task(latest revision) - Service name:
frontend-service - Desired tasks:
2
Networking
- VPC: Select your VPC
- Subnets: Select both PRIVATE subnets
- Security groups: Select
ECS-SG - Auto-assign public IP: DISABLED
Load Balancing
- Select “Application Load Balancer”
- Load balancer name: Select
ecs-alb - Click “Add to load balancer”
- Production listener port:
80:HTTP - Target group name: Select
frontend-tg
Deployment Configuration
- Deployment type: Rolling update
- Minimum healthy percent:
100 - Maximum percent:
200
Deployment Circuit Breaker
- Enable “Enable rollback on failure”
Click “Create” and wait for service to stabilize
Create Backend Service:
Create Service
Same process as frontend, but with these differences:
- Task definition:
backend-task - Service name:
backend-service - Target group:
backend-tg
Click “Create” and wait for service to stabilize
✅ Infrastructure Setup Complete!
All resources are now created. Verify deployment:
- Check ECS Services show “Running” status
- Check Target Groups show “healthy” targets
- Test ALB DNS name in browser
- Check CloudWatch Logs for application output
✅ Infrastructure Setup Checklist
Complete these resources before proceeding to CI/CD:
❓ Frequently Asked Questions & Scenarios
This section answers common questions in a simple way so both technical and non-technical people can understand the overall concepts.
Great for: Reviewing concepts, interviewing, or explaining the architecture to your team.
30 Common Questions (with Simple Explanations)
Core Concepts & Big Picture
- Q1: What problem does this whole ECS setup solve?
A: It gives you a repeatable, reliable way to run your app in the cloud. Instead of running code on one fragile server, you package your app in containers, run them on ECS, and put an ALB in front so users always hit a healthy instance. - Q2: What is a container in simple words?
A: A container is like a small, portable box that holds your app and everything it needs to run (libraries, runtime). If it runs on your laptop, it will run the same way in AWS. - Q3: How is ECS different from just using EC2 directly?
A: With EC2 you manage servers yourself (patching, scaling, scheduling). With ECS, you tell AWS “run these containers like this” and ECS handles placement, health checks, and restarts for you. - Q4: Why do we need an ALB in front of ECS?
A: ECS tasks (containers) come and go. The ALB is the stable entry point that knows which tasks are healthy and where to send each request. It also supports path-based routing, HTTPS, and health checks. - Q5: Why do we use Fargate instead of EC2 launch type?
A: Fargate is “serverless for containers”. You don’t manage EC2 instances; you only define CPU/memory per task. AWS manages the underlying servers, which reduces ops work. - Q6: What is the difference between an ECS Task Definition and an ECS Service?
A: The task definition is the blueprint (what to run, image, CPU, env vars). The service is the “manager” that ensures a certain number of those tasks are running and connected to the load balancer. - Q7: Why do we keep the database (RDS) in private subnets?
A: So it’s not exposed to the internet. Only ECS tasks inside the VPC can talk to it, which is a big security win. - Q8: Why do we split frontend and backend into separate services?
A: They scale differently and have different behavior. Splitting them lets you scale, deploy, and debug each independently. - Q9: What is the role of ECR in this architecture?
A: ECR is a private Docker image registry. It stores your built images so ECS can pull them whenever it needs to start new tasks. - Q10: Why do we use CI/CD instead of manual deployments?
A: CI/CD turns deployment into a repeatable, automated process. Every push builds, tests, and deploys in the same way, reducing human error and speeding up releases.
Networking, Security & Reliability
- Q11: Why do we have both public and private subnets?
A: Public subnets host internet-facing resources (like the ALB). Private subnets host sensitive workloads (ECS tasks, RDS) that should not be directly reachable from the internet. - Q12: How do ECS tasks access the internet if they are in private subnets?
A: They go out through a NAT Gateway. This lets tasks download packages or talk to external APIs without being directly reachable from the internet. - Q13: What are Security Groups in this setup?
A: Security Groups are virtual firewalls. For example, the ALB SG allows traffic from the internet on HTTP/HTTPS, and the ECS SG only allows traffic from the ALB SG. - Q14: How do we ensure only ECS tasks can talk to the database?
A: The RDS Security Group only allows connections from the ECS Security Group on the database port. No other source is allowed. - Q15: What happens if one ECS task crashes?
A: The ECS service detects that the task is unhealthy and starts a new one. The ALB stops sending traffic to the unhealthy task automatically. - Q16: How do health checks protect users?
A: The ALB pings a health check endpoint (like/or/api/health). Only tasks that respond correctly are considered healthy and receive user traffic. - Q17: What is the difference between task execution role and task role?
A: The execution role is used by ECS to pull images and write logs. The task role is used by your app code to call AWS services (like S3, Parameter Store). - Q18: How do we keep secrets (like DB password) out of the code?
A: We store them in Parameter Store as SecureString values and let ECS inject them into the task as environment variables or secrets. The code just reads env vars. - Q19: How does scaling work in this design?
A: The ECS service can be configured to scale the number of running tasks up or down based on metrics (CPU, requests). The ALB automatically balances traffic across all tasks. - Q20: What is the main single point of failure to watch out for?
A: Misconfigured health checks, database availability, and limits like connection pools. The infrastructure is multi-AZ and managed, but bad configuration can still cause downtime.
CI/CD, Task Definitions & Operations
- Q21: What does the GitHub Actions workflow actually do step by step?
A: It checks out code, configures AWS credentials, logs in to ECR, builds a Docker image, pushes it to ECR, updates the task definition with the new image, and asks ECS to deploy it. - Q22: Why do we tag images with the Git SHA?
A: The Git SHA is a unique identifier for each commit. Tagging images with it makes deployments traceable and makes rollbacks easier. - Q23: How does ECS know which image to run after a deployment?
A: The task definition is updated with the new image URI (including tag). The ECS service always runs the latest revision of the task definition. - Q24: What is a “task definition revision”?
A: Every time you change the task definition (for example, new image or env var), ECS creates a new numbered revision. Services usually point to the latest revision. - Q25: How do CloudWatch Logs fit into this?
A: Each container sends its stdout/stderr logs to a log group (like/ecs/frontend). You can search, filter, and debug issues centrally in CloudWatch. - Q26: What should I look at first when the app is “not working”?
A: Check ECS service events (for deployment errors), ALB target health, and CloudWatch logs for the relevant task. This usually tells you if it’s a code error, health check issue, or config problem. - Q27: How do I roll back to a previous version?
A: You can either re-deploy an older image tag via CI/CD, or manually update the service to use an older task definition revision that points to the previous image. - Q28: Why do we separate environment variables and secrets?
A: Regular env vars hold non-sensitive config (like URLs); secrets are sensitive values stored in a secure service (Parameter Store) and injected securely. This reduces risk if logs or screenshots leak. - Q29: How does this design support future growth?
A: You can add more services (microservices), scale tasks independently, add caching layers, and extend CI/CD, all without redesigning the whole system. The building blocks are already in place. - Q30: How would you explain this architecture to a non‑technical stakeholder?
A: We have a front door (ALB) that safely receives traffic, smart workers (ECS tasks) that handle requests, a secure vault (RDS + Parameter Store) for data and secrets, and an assembly line (CI/CD) that ships new versions automatically and safely.
10 Practical Scenarios
Operational Troubleshooting
- S1: New deployment, ALB shows 502/503 errors.
How to think: Check ALB target health → confirm health check path exists and returns 200 → verify container listens on the right port → check CloudWatch logs for startup errors. - S2: Tasks keep going to Stopped state right after starting.
How to think: Look at the “stopped reason” in ECS → inspect container logs → common issues: wrong env vars, DB not reachable, port conflicts, or app crashes on boot. - S3: Database CPU is high and app feels slow.
How to think: Check connection counts, slow queries, and indexing → consider connection pooling, query optimization, and potentially scaling RDS (larger instance or read replicas). - S4: Suddenly many 5xx errors during peak traffic.
How to think: Check ECS service metrics (CPU/memory) → if tasks are maxed out, increase desired count or add auto scaling → ensure ALB health checks and timeouts are set correctly. - S5: A secret (like DB password) changed and app can’t connect.
How to think: Update the value in Parameter Store → confirm the ECS task definition still references the correct parameter name → redeploy tasks so they pick up the new value.
Design & Architecture Decisions
- S6: You need to add a new microservice (for example, reporting API).
Approach: Create a new ECR repo and ECS task definition, a new ECS service, and (optionally) a new path rule on the ALB (like/reports/*). Wire it into CI/CD the same way as backend. - S7: You want a staging environment separate from production.
Approach: Duplicate the stack in another VPC or another set of subnets with separate ECS cluster, RDS, and ALB. Use different DNS and separate CI/CD workflows pointing to staging resources. - S8: Frontend needs to call a third‑party API from the backend only.
Approach: Keep the API key in Parameter Store, inject into backend task, and call the third‑party service from backend code. Frontend never sees the secret. - S9: You want zero‑downtime database migrations.
Approach: Use migration tools (Prisma, Flyway, Liquibase) in a separate step or job before/with deployment, design migrations to be backward compatible, and roll out app changes after DB schema supports both versions. - S10: You want to explain cloud costs to a manager.
Approach: Break it down: “We pay for compute (Fargate tasks), storage (RDS & ECR), traffic and security (ALB & NAT), and observability (CloudWatch). We can control each of these with scaling, instance sizes, and retention policies.”
Complete Terraform Guide
Learn more about Rails
Learn more about Mern Stack
Learn more about DevOps



Nice
https://shorturl.fm/5xcAq