Amazon ECS Public vs Private Subnets
A practical guide to ECS networking tradeoffs, public and private subnet design, ALB placement, NAT gateways, VPC endpoints, and production architecture.
Amazon Elastic Container Service (ECS) runs containerized workloads as tasks. These tasks require compute capacity, networking, permissions, logging, and access to other services.
This guide explains:
- How ECS tasks use VPC networking
- The difference between public and private subnets
- Resources required for each architecture
- Inbound and outbound traffic flow
- Security groups and network ACLs
- NAT Gateway and VPC endpoint usage
- Availability, cost, and security tradeoffs
- Recommended architecture for production workloads
1. ECS Networking Overview
Amazon ECS supports two main compute models:
AWS Fargate
AWS manages the underlying servers. You define the task CPU, memory, networking, and container configuration.
ECS on EC2
You provision and manage EC2 instances that join an ECS cluster. ECS schedules containers onto those instances.
For most new serverless container deployments, ECS with Fargate is the simpler option.
2. How Fargate Tasks Connect to a VPC
Fargate tasks use the awsvpc network mode.
Each running task receives its own:
- Elastic Network Interface (ENI)
- Private IP address
- Security group
- Subnet placement
- Optional public IP address
From a network perspective, each task behaves similarly to a small virtual machine inside the VPC.
Example ECS service configuration:
network_configuration {
subnets = var.private_subnet_ids
security_groups = [aws_security_group.ecs_tasks.id]
assign_public_ip = false
}
The selected subnet determines the task’s routing behavior.
3. What Makes a Subnet Public or Private?
A subnet is classified by its route table, not by its name.
Public subnet
A public subnet has a default route to an Internet Gateway:
VPC CIDR -> local
0.0.0.0/0 -> Internet Gateway
A resource in the subnet must also have a public IPv4 address or Elastic IP to communicate directly through the Internet Gateway.
Private subnet
A private subnet does not have a direct route to an Internet Gateway.
It commonly routes outbound internet traffic through a NAT Gateway:
VPC CIDR -> local
0.0.0.0/0 -> NAT Gateway
Resources in a private subnet normally have private IP addresses only.
4. ECS Tasks in Public Subnets
A Fargate task can run in a public subnet with a public IP address.
network_configuration {
subnets = var.public_subnet_ids
security_groups = [aws_security_group.ecs_tasks.id]
assign_public_ip = true
}
Traffic flow:
Internet
|
v
Internet Gateway
|
v
ECS Task Public IP
The task also retains a private IP address inside the VPC.
Important
A public IP does not automatically expose every container port.
The task’s security group still controls which inbound connections are allowed.
5. Resources Required for Public ECS Tasks
A basic public-subnet ECS deployment may require:
- VPC
- At least two public subnets
- Internet Gateway
- Public route table
- ECS cluster
- ECS task definition
- ECS service
- Task execution IAM role
- Application task IAM role
- ECS task security group
- ECR repository
- CloudWatch log group
- Application Load Balancer, if applicable
- ALB security group
- Target group
- Listener and listener rules
- ACM certificate for HTTPS
- DNS record
A NAT Gateway is generally not required because tasks can access the internet using their assigned public IP addresses.
6. Advantages of Public ECS Tasks
- Simpler VPC architecture
- No NAT Gateway cost
- Direct outbound internet access
- Easier initial troubleshooting
- Suitable for development environments and proofs of concept
- Fewer route tables and networking components
7. Disadvantages of Public ECS Tasks
- Every task may receive a publicly routable IP address
- Larger potential attack surface
- Accidental security group changes may expose task ports
- Public IPs change when tasks are replaced
- Difficult to maintain a stable outbound allow-listed IP
- Less suitable for sensitive or regulated workloads
- Tasks may bypass the load balancer if security groups are misconfigured
Public task IP addresses should not normally be used as application endpoints because ECS tasks are ephemeral and may be replaced during deployments, failures, or scaling events.
8. Secure Public-Subnet Task Configuration
A task may have a public IP while still accepting inbound traffic only from the Application Load Balancer.
ALB security group
Inbound:
TCP 443 from 0.0.0.0/0
Outbound:
Application port to ECS task security group
ECS task security group
Inbound:
TCP 3000 from ALB security group only
Outbound:
Required destinations and ports
Avoid this configuration:
Inbound:
TCP 3000 from 0.0.0.0/0
unless the task intentionally needs direct public access.
9. ECS Tasks in Private Subnets
The most common production architecture places ECS tasks in private subnets.
network_configuration {
subnets = var.private_subnet_ids
security_groups = [aws_security_group.ecs_tasks.id]
assign_public_ip = false
}
Typical architecture:
Internet
|
v
Internet Gateway
|
v
Application Load Balancer
Public Subnets
|
v
ECS Fargate Tasks
Private Subnets
|
v
NAT Gateway
Public Subnet
|
v
Internet
The ECS tasks do not need public IP addresses.
The ALB forwards requests to the tasks using their private IP addresses.
10. Inbound and Outbound Traffic Are Separate
A private ECS architecture has different paths for inbound and outbound traffic.
Inbound traffic
Client
-> Internet Gateway
-> Public Application Load Balancer
-> Private ECS Task
Outbound traffic
Private ECS Task
-> NAT Gateway
-> Internet Gateway
-> External Service
The NAT Gateway supports outbound connections initiated by the ECS task.
It does not allow arbitrary internet clients to initiate inbound connections to the private task.
11. Resources Required for Private ECS Tasks
A private-subnet deployment typically requires:
Core ECS resources
- ECS cluster
- ECS task definition
- ECS service
- Task execution IAM role
- Task application IAM role
- ECS task security group
- ECR repository
- CloudWatch log group
Networking resources
- VPC
- At least two public subnets
- At least two private subnets
- Internet Gateway
- Public route table
- Private route table
- One or more NAT Gateways
- Elastic IP address for each NAT Gateway
Ingress resources
- Internet-facing Application Load Balancer
- ALB security group
- Target group
- HTTPS listener
- Listener rules
- ACM certificate
- DNS record
12. Example Route Tables
Public subnet route table
Destination Target
--------------- ----------------
10.0.0.0/16 local
0.0.0.0/0 Internet Gateway
Private subnet route table
Destination Target
--------------- ----------------
10.0.0.0/16 local
0.0.0.0/0 NAT Gateway
The ALB and ECS tasks can communicate through the VPC’s local route.
They do not need to be in the same subnet.
13. Advantages of Private ECS Tasks
- Tasks cannot be contacted directly from the internet
- Smaller attack surface
- Public traffic must pass through the load balancer
- Better separation between ingress and application layers
- Stable outbound IP through a NAT Gateway Elastic IP
- Easier external firewall and API allow-listing
- Better fit for production and regulated workloads
- Easier to enforce centralized ingress controls such as AWS WAF
14. Disadvantages of Private ECS Tasks
- NAT Gateway hourly charges
- NAT Gateway data-processing charges
- More route tables and network resources
- More Terraform configuration
- Additional troubleshooting complexity
- A single NAT Gateway may introduce an Availability Zone dependency
- One NAT Gateway per Availability Zone improves resilience but increases cost
15. Application Load Balancer Placement
For a public web application, the ALB should normally run in public subnets.
resource "aws_lb" "app" {
name = "app-alb"
internal = false
load_balancer_type = "application"
subnets = var.public_subnet_ids
security_groups = [aws_security_group.alb.id]
}
The ECS tasks can run in private subnets:
network_configuration {
subnets = var.private_subnet_ids
security_groups = [aws_security_group.ecs_tasks.id]
assign_public_ip = false
}
The traffic flow is:
Public ALB
|
| Private VPC traffic
v
Private ECS Tasks
A public ALB does not require the ECS tasks to be public.
16. Security Group Design
Use separate security groups for the ALB and ECS tasks.
ALB security group
resource "aws_security_group" "alb" {
name = "app-alb-sg"
vpc_id = aws_vpc.main.id
ingress {
from_port = 443
to_port = 443
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
egress {
from_port = 3000
to_port = 3000
protocol = "tcp"
security_groups = [aws_security_group.ecs_tasks.id]
}
}
ECS task security group
resource "aws_security_group" "ecs_tasks" {
name = "app-ecs-tasks-sg"
vpc_id = aws_vpc.main.id
ingress {
from_port = 3000
to_port = 3000
protocol = "tcp"
security_groups = [aws_security_group.alb.id]
}
egress {
from_port = 443
to_port = 443
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
}
The key pattern is:
ECS inbound source = ALB security group
instead of:
ECS inbound source = 0.0.0.0/0
17. Security Groups vs. Network ACLs
Security groups and Network ACLs operate at different levels.
Security groups
- Attached to ENIs
- Stateful
- Support allow rules
- Can reference other security groups
- Best suited for application-level access controls
Network ACLs
- Applied to subnets
- Stateless
- Support allow and deny rules
- Require explicit return-traffic rules
- Useful as an additional subnet boundary
For most ECS deployments:
Security groups = primary control
Network ACLs = secondary control
Overly restrictive Network ACLs can cause difficult-to-diagnose failures because return traffic and ephemeral ports must be explicitly permitted.
18. Outbound Connectivity Requirements
An ECS task may require outbound connectivity to:
- Pull images from Amazon ECR
- Download image layers from Amazon S3
- Send logs to CloudWatch Logs
- Retrieve secrets from Secrets Manager
- Decrypt secrets using AWS KMS
- Call third-party APIs
- Connect to MongoDB Atlas
- Contact an identity provider
- Send telemetry
- Call AWS APIs
Private tasks therefore need one or more of the following:
- NAT Gateway
- VPC endpoints
- AWS PrivateLink
- VPC peering
- Site-to-Site VPN
- Transit Gateway
- Direct Connect
19. Private ECS Tasks Without a NAT Gateway
A private ECS service can operate without internet access by using VPC endpoints.
Private ECS Task
|
+--> ECR API VPC Endpoint
+--> ECR Docker VPC Endpoint
+--> S3 Gateway Endpoint
+--> CloudWatch Logs Endpoint
+--> Secrets Manager Endpoint
+--> KMS Endpoint
+--> STS Endpoint
Common endpoints include:
ecr.apiecr.dkrlogssecretsmanagerkmssts- S3 gateway endpoint
Advantages
- No direct internet access
- AWS service traffic remains within AWS networking
- Reduced exposure
- Can remove NAT Gateway dependency
- Useful for regulated workloads
Disadvantages
- Interface endpoints have hourly charges
- Endpoint costs multiply across Availability Zones
- More DNS and security group configuration
- External APIs remain unreachable without another egress path
- May be more expensive than one NAT Gateway for smaller systems
20. Hybrid NAT and VPC Endpoint Architecture
Many production systems use both NAT Gateway and VPC endpoints.
AWS service traffic
-> VPC endpoints
External API traffic
-> NAT Gateway
For example:
ECR, S3, CloudWatch Logs, Secrets Manager
-> VPC endpoints
MongoDB Atlas, OpenAI, GCP APIs, SaaS services
-> NAT Gateway
This can reduce NAT traffic while preserving access to external services.
21. MongoDB Atlas Connectivity
An ECS application connecting to MongoDB Atlas commonly uses one of three approaches.
Option 1: NAT Gateway with Elastic IP
Private ECS Task
|
v
NAT Gateway Elastic IP
|
v
MongoDB Atlas Public Endpoint
Add the NAT Gateway’s Elastic IP address to the MongoDB Atlas IP access list.
Advantages:
- Stable outbound IP
- Easy to understand
- Works with private ECS tasks
Option 2: Public task IPs
Each Fargate task receives a public IP.
This is less suitable for Atlas IP allow-listing because task IP addresses may change during:
- Deployments
- Scaling
- Health-check replacement
- Infrastructure maintenance
- Task restarts
Avoid allowing 0.0.0.0/0 in MongoDB Atlas only to support changing ECS public IPs.
Option 3: Private connectivity
Depending on the Atlas configuration, use:
- AWS PrivateLink
- VPC peering
- Transit Gateway connectivity
Private connectivity provides stronger isolation but requires additional setup and may have additional cost.
22. Availability Zone Design
Production ECS services should normally span at least two Availability Zones.
Availability Zone A
├── Public Subnet A
│ ├── ALB Node
│ └── NAT Gateway A
└── Private Subnet A
└── ECS Tasks
Availability Zone B
├── Public Subnet B
│ ├── ALB Node
│ └── NAT Gateway B
└── Private Subnet B
└── ECS Tasks
The ECS service distributes tasks across the configured subnets and Availability Zones.
23. One NAT Gateway vs. One per Availability Zone
One NAT Gateway
2 public subnets
2 private subnets
1 NAT Gateway
Advantages:
- Lower fixed cost
- Simpler configuration
- Often sufficient for development and staging
Disadvantages:
- Single Availability Zone dependency for outbound traffic
- Cross-AZ data transfer may occur
- NAT failure or AZ disruption can affect all private tasks
NAT Gateway per Availability Zone
2 public subnets
2 private subnets
2 NAT Gateways
Each private subnet routes to the NAT Gateway in the same Availability Zone.
Advantages:
- Better fault isolation
- Higher availability
- Avoids cross-AZ NAT routing
Disadvantages:
- Higher fixed cost
- Additional Elastic IP addresses
- More route tables and Terraform resources
24. Cost Comparison
| Architecture | NAT Cost | Endpoint Cost | Security | Complexity |
|---|---|---|---|---|
| Public tasks with public IPs | None | None | Moderate | Low |
| Private tasks with one NAT Gateway | Medium | Optional | Strong | Medium |
| Private tasks with NAT per AZ | Higher | Optional | Strong | Medium |
| Private tasks with only VPC endpoints | None | Potentially high | Very strong | High |
| Private tasks with NAT and endpoints | Medium | Medium | Strong and flexible | High |
For small ECS environments, the NAT Gateway may be one of the largest fixed networking costs.
A common strategy is:
- Development: public tasks or one shared NAT Gateway
- Staging: private tasks with one NAT Gateway
- Production: private tasks with NAT per Availability Zone
The appropriate choice depends on risk, availability requirements, external dependencies, and budget.
25. IAM Roles Required by ECS
ECS commonly uses two separate IAM roles.
Task execution role
Used by the ECS platform to:
- Pull images from ECR
- Write container logs
- Retrieve secrets referenced by the task definition
Example managed policy:
AmazonECSTaskExecutionRolePolicy
Task role
Used by the application running inside the container.
Examples:
- Read objects from S3
- Send messages to SQS
- Query DynamoDB
- Invoke Lambda
- Read application-specific secrets
Do not place application permissions in the execution role.
Follow least privilege for both roles.
26. TLS and HTTPS
For an internet-facing web application:
Client
-> HTTPS
-> Application Load Balancer
-> HTTP or HTTPS
-> ECS Task
The ALB commonly terminates TLS using an ACM certificate.
Internet-facing listener
TCP 443
ACM certificate
TLS policy
The ALB can forward traffic to the container over:
- HTTP inside the VPC
- HTTPS for end-to-end encryption
Using HTTPS between the ALB and tasks may be required for stricter compliance environments.
27. Additional Security Considerations
Restrict direct task access
Allow inbound application traffic only from the ALB security group.
Apply least-privilege egress
Avoid permitting all outbound traffic when the destinations are predictable.
Where practical, restrict by:
- Destination security group
- VPC endpoint
- Prefix list
- CIDR
- Port
- Protocol
Protect the ALB
Consider:
- AWS WAF
- Rate-based rules
- Managed rule groups
- Corporate IP restrictions
- Authentication through Cognito or an identity provider
Store secrets securely
Use:
- AWS Secrets Manager
- AWS Systems Manager Parameter Store
- AWS KMS
Do not store credentials directly in:
- Docker images
- Source code
- Terraform source
- ECS environment variables committed to Git
Enable logging
Recommended logs include:
- ECS container logs
- ALB access logs
- VPC Flow Logs
- AWS CloudTrail
- AWS WAF logs
- Application audit logs
Avoid privileged containers
Do not run containers as root unless required.
Use:
- Read-only root filesystems
- Non-root users
- Minimal base images
- Image vulnerability scanning
- Resource limits
- Health checks
Use immutable deployments
Deploy new task definition revisions instead of editing running containers.
28. ECS on EC2 Differences
ECS on EC2 introduces another infrastructure layer.
ECS Task
|
v
EC2 Container Instance
|
v
Subnet and Route Table
Available networking modes include:
bridgehostawsvpc
With awsvpc, each task receives its own ENI and security groups.
With bridge or host, tasks rely more heavily on the EC2 instance’s network configuration.
Additional EC2-mode resources may include:
- Auto Scaling Group
- EC2 Launch Template
- ECS-optimized AMI
- EC2 instance IAM role
- Capacity provider
- EC2 security group
- Instance patching and maintenance
- Scaling policies
Fargate removes the need to manage these EC2 resources.
29. Recommended Production Architecture
For a public React and Node.js application running on ECS Fargate:
Internet
|
v
Route 53 or External DNS
|
v
Application Load Balancer
Public Subnets
|
v
ECS Fargate Service
Private Subnets
|
+--> MongoDB Atlas
|
+--> External APIs
|
+--> AWS Services
|
v
NAT Gateway or VPC Endpoints
Recommended configuration:
Public subnets
Host:
- Internet-facing ALB
- NAT Gateway
Private subnets
Host:
- ECS Fargate tasks
- Internal application services
Security groups
ALB Security Group:
Inbound TCP 443 from approved clients
Outbound application port to ECS security group
ECS Security Group:
Inbound application port from ALB security group only
Outbound only to required destinations
ECS service
network_configuration {
subnets = var.private_subnet_ids
security_groups = [aws_security_group.ecs_tasks.id]
assign_public_ip = false
}
ALB
resource "aws_lb" "app" {
internal = false
load_balancer_type = "application"
subnets = var.public_subnet_ids
security_groups = [aws_security_group.alb.id]
}
30. Recommended Development Architecture
For a low-cost development environment, either of the following may be reasonable.
Option A: Public tasks with strict security groups
Public ALB
|
v
Public ECS Tasks
Use:
assign_public_ip = true
Ensure that task inbound access is allowed only from the ALB security group.
Option B: Private tasks with one NAT Gateway
Public ALB
|
v
Private ECS Tasks
|
v
Single NAT Gateway
This more closely resembles production while controlling cost.
31. Decision Guide
Use public ECS tasks when:
- The environment is temporary or non-production
- NAT Gateway cost is a major concern
- The task has no sensitive inbound service
- Security groups are tightly controlled
- Stable outbound IP allow-listing is not required
Use private ECS tasks when:
- The workload is production-facing
- The application handles sensitive information
- All inbound traffic should pass through an ALB
- A stable outbound IP is required
- External systems use IP allow-listing
- Security and compliance are priorities
Use private tasks without NAT when:
- The workload must not access the public internet
- All dependencies are available through private networking
- VPC endpoint cost and complexity are acceptable
- Strong isolation is required
32. Final Recommendation
For most production ECS applications:
Place the internet-facing Application Load Balancer in public subnets and place ECS tasks in private subnets.
Use a NAT Gateway when tasks must access public services.
Use VPC endpoints for private access to AWS services and to reduce unnecessary NAT traffic.
The central design principle is:
Only the resource that must receive internet traffic should be public.
For a standard ECS web application:
Public:
Application Load Balancer
NAT Gateway
Private:
ECS Tasks
Databases
Internal Services
This provides a strong balance between security, maintainability, scalability, and operational simplicity.