Many AWS newcomers get confused about NAT Gateway placement because the distinction between public and private subnets isn't always clear-cut. Let's break down the technical reasoning:
// Typical VPC setup with NAT (CloudFormation snippet)
Resources:
PublicSubnet:
Type: AWS::EC2::Subnet
Properties:
VpcId: !Ref VPC
CidrBlock: 10.0.1.0/24
MapPublicIpOnLaunch: true
PrivateSubnet:
Type: AWS::EC2::Subnet
Properties:
VpcId: !Ref VPC
CidrBlock: 10.0.2.0/24
NatGateway:
Type: AWS::EC2::NatGateway
Properties:
AllocationId: !Ref EIP
SubnetId: !Ref PublicSubnet // Critical placement
A NAT Gateway needs internet access to function - it's essentially translating private IP traffic to a public IP. The traffic flow looks like this:
- Private instance → NAT Gateway (public subnet)
- NAT Gateway → Internet Gateway
- Internet Gateway → Public internet
While the NAT Gateway resides in a public subnet, it's protected by AWS's security model:
- Only outbound traffic is allowed (stateful)
- No inbound initiation from internet
- Managed by AWS (unlike NAT instances)
Here's how you'd implement this in Terraform:
resource "aws_nat_gateway" "example" {
allocation_id = aws_eip.example.id
subnet_id = aws_subnet.public.id # Must be public
tags = {
Name = "NAT GW Public Subnet"
}
}
resource "aws_route_table" "private" {
vpc_id = aws_vpc.example.id
route {
cidr_block = "0.0.0.0/0"
nat_gateway_id = aws_nat_gateway.example.id
}
}
Watch for these mistakes:
Error | Result |
---|---|
NAT in private subnet | Connectivity timeout |
No IGW route in public subnet | NAT cannot reach internet |
Wrong route table association | Private instances bypass NAT |
In AWS networking, the placement of NAT Gateways often causes confusion. While many engineers assume NAT Gateways should reside in private subnets, AWS documentation consistently recommends placing them in public subnets. Let's break down why this architecture makes sense.
First, let's clarify the core concepts:
Public Subnet:
- Has a route to an Internet Gateway (IGW) in its route table
- Can initiate outbound internet connections
- Can receive inbound connections from the internet
Private Subnet:
- No direct route to an IGW
- Cannot initiate outbound internet connections directly
- Cannot receive inbound connections from the internet
The NAT Gateway needs internet access to function - it's essentially translating private IP addresses to a public one for outbound connections. Here's the technical rationale:
- Internet Access Requirement: NAT Gateway needs to communicate with the internet to forward traffic from private instances
- Route Table Configuration: Public subnets have the 0.0.0.0/0 route pointing to the IGW
- Security: NAT Gateway itself shouldn't be directly accessible from the internet, but needs outbound access
Here's how to properly set up a NAT Gateway in a public subnet using AWS CDK (TypeScript):
import * as cdk from 'aws-cdk-lib';
import * as ec2 from 'aws-cdk-lib/aws-ec2';
export class NatGatewayStack extends cdk.Stack {
constructor(scope: cdk.App, id: string, props?: cdk.StackProps) {
super(scope, id, props);
// Create VPC with public and private subnets
const vpc = new ec2.Vpc(this, 'VPC', {
natGateways: 1,
subnetConfiguration: [
{
name: 'Public',
subnetType: ec2.SubnetType.PUBLIC,
},
{
name: 'Private',
subnetType: ec2.SubnetType.PRIVATE_WITH_EGRESS,
}
]
});
// The NAT Gateway is automatically placed in the public subnet
// and private subnets are configured to route through it
}
}
When working with NAT Gateways, watch out for these pitfalls:
- Placing NAT Gateway in a private subnet (won't have internet access)
- Forgetting to allocate elastic IPs for the NAT Gateway
- Not updating private subnet route tables to point to the NAT Gateway
- Using NAT Instances instead of NAT Gateways without proper security group rules
NAT Gateways in public subnets offer several advantages:
Metric | Public Subnet NAT | Private Subnet NAT |
---|---|---|
Throughput | Up to 45 Gbps | Limited by additional hops |
Availability | Highly available (AWS managed) | Depends on custom setup |
Cost | Standard pricing | Additional routing costs |
While NAT Gateways reside in public subnets, they're still secure:
- NAT Gateways don't accept inbound connections from the internet
- They only allow outbound connections initiated from private instances
- AWS manages the security aspects of the NAT Gateway service
- No security groups are applied to NAT Gateways (unlike NAT Instances)
While the public subnet placement is standard, there are exceptions:
NAT Instances: If you must use EC2 instances as NAT devices (instead of the managed NAT Gateway service), you'll need to:
- Place them in public subnets
- Configure proper security groups
- Disable source/destination checks
PrivateLink Endpoints: For accessing AWS services, consider VPC endpoints to avoid NAT Gateway costs entirely.