Where Are NAT Gateways Typically Placed in an AWS VPC? A Complete Placement Guide
NAT gateways are always provisioned in a public subnet so that instances in private subnets can initiate outbound internet traffic while remaining protected from inbound connections.
The litu54/DevOps-Interview-Guide repository aggregates real-world DevOps interview questions from companies including Persistent Systems, Sigmoid, Capgemini, and Arrise Solutions, consistently highlighting that where NAT gateways are placed within an AWS VPC is a critical architectural concept tested during technical screenings. Understanding the distinction between public and private subnet placement is essential for designing secure, fault-tolerant network infrastructure on AWS.
Why NAT Gateways Require Public Subnet Placement
A NAT gateway must be created in a public subnet—specifically, a subnet that has a route to an Internet Gateway (IGW). This placement is architectural, not optional. The NAT gateway itself needs direct internet connectivity to perform Network Address Translation for private instances.
As documented in Persistent_Systems/DevOps_Engineer_1.md, the interview question "Where does NATGateway reside" confirms this requirement. The file Sigmoid/DevOps_Engineer_4.md reinforces this when discussing cluster requirements, noting that the NAT gateway's Elastic Network Interface (ENI) must reside in a subnet with IGW access.
Route Table Configuration and Traffic Flow
The separation of concerns between public and private subnets is managed through route tables. While the NAT gateway physically exists in the public subnet, private subnets access it through specific routing entries.
Public Subnet Routing
The public subnet hosting the NAT gateway must have a route table with a default route (0.0.0.0/0) pointing to the Internet Gateway. This allows the gateway to communicate with external destinations and receive return traffic.
Private Subnet Routing
Private subnets do not contain routes to the IGW. Instead, their route tables direct internet-bound traffic (0.0.0.0/0) to the NAT gateway ID. This configuration, referenced in Arrise_Solutions/DevOps_Engineer.md, ensures that instances without public IP addresses can reach the internet through the NAT gateway's public IP.
High Availability and Multi-AZ Deployment
For production workloads, deploy one NAT gateway per Availability Zone (AZ). Each private subnet should route to the NAT gateway in the same AZ to eliminate single points of failure and avoid cross-AZ data transfer charges. If an AZ becomes unavailable, instances in other AZs retain internet connectivity through their local NAT gateway.
Infrastructure as Code Examples
The following configurations demonstrate the correct placement of NAT gateways in public subnets using Terraform, AWS CLI, and CloudFormation.
Terraform Configuration
This example from the repository analysis creates a NAT gateway in a public subnet and configures a private subnet to route through it:
resource "aws_vpc" "example" {
cidr_block = "10.0.0.0/16"
}
# Public subnet (has route to IGW)
resource "aws_subnet" "public" {
vpc_id = aws_vpc.example.id
cidr_block = "10.0.1.0/24"
availability_zone = "us-east-1a"
map_public_ip_on_launch = true
}
# Private subnet (no direct IGW)
resource "aws_subnet" "private" {
vpc_id = aws_vpc.example.id
cidr_block = "10.0.2.0/24"
availability_zone = "us-east-1a"
}
# Internet Gateway
resource "aws_internet_gateway" "igw" {
vpc_id = aws_vpc.example.id
}
# Public route table (for public subnet)
resource "aws_route_table" "public_rt" {
vpc_id = aws_vpc.example.id
route {
cidr_block = "0.0.0.0/0"
gateway_id = aws_internet_gateway.igw.id
}
}
resource "aws_route_table_association" "public_assoc" {
subnet_id = aws_subnet.public.id
route_table_id = aws_route_table.public_rt.id
}
# Elastic IP for NAT gateway
resource "aws_eip" "nat_eip" {
vpc = true
}
# NAT Gateway in the public subnet
resource "aws_nat_gateway" "natgw" {
allocation_id = aws_eip.nat_eip.id
subnet_id = aws_subnet.public.id
depends_on = [aws_internet_gateway.igw]
}
# Private route table (points to NAT)
resource "aws_route_table" "private_rt" {
vpc_id = aws_vpc.example.id
route {
cidr_block = "0.0.0.0/0"
nat_gateway_id = aws_nat_gateway.natgw.id
}
}
resource "aws_route_table_association" "private_assoc" {
subnet_id = aws_subnet.private.id
route_table_id = aws_route_table.private_rt.id
}
AWS CLI Verification
Verify the subnet placement using the AWS CLI:
# List NAT gateways
aws ec2 describe-nat-gateways
# Show details of a specific NAT gateway (replace <nat-gateway-id>)
aws ec2 describe-nat-gateways --nat-gateway-ids <nat-gateway-id> \
--query "NatGateways[0].SubnetId" --output text
CloudFormation Template
A minimal CloudFormation template placing the NAT gateway in a public subnet:
Resources:
VPC:
Type: AWS::EC2::VPC
Properties:
CidrBlock: 10.0.0.0/16
PublicSubnet:
Type: AWS::EC2::Subnet
Properties:
VpcId: !Ref VPC
CidrBlock: 10.0.1.0/24
MapPublicIpOnLaunch: true
AvailabilityZone: us-east-1a
InternetGateway:
Type: AWS::EC2::InternetGateway
AttachGateway:
Type: AWS::EC2::VPCGatewayAttachment
Properties:
VpcId: !Ref VPC
InternetGatewayId: !Ref InternetGateway
PublicRouteTable:
Type: AWS::EC2::RouteTable
Properties:
VpcId: !Ref VPC
PublicRoute:
Type: AWS::EC2::Route
Properties:
RouteTableId: !Ref PublicRouteTable
DestinationCidrBlock: 0.0.0.0/0
GatewayId: !Ref InternetGateway
PublicSubnetRouteTableAssociation:
Type: AWS::EC2::SubnetRouteTableAssociation
Properties:
SubnetId: !Ref PublicSubnet
RouteTableId: !Ref PublicRouteTable
NatEIP:
Type: AWS::EC2::EIP
Properties:
Domain: vpc
NatGateway:
Type: AWS::EC2::NatGateway
Properties:
AllocationId: !GetAtt NatEIP.AllocationId
SubnetId: !Ref PublicSubnet
Cost and Security Considerations
Placing NAT gateways in public subnets optimizes both cost and security posture. NAT gateways incur hourly availability charges and data processing fees; routing through a public subnet avoids unnecessary cross-AZ transfer costs. From a security perspective, this architecture ensures private subnet instances remain unreachable from the internet while allowing outbound connections for updates and API calls, as detailed in Capgemini/DevOps_Engineer_3.md when contrasting NAT Gateways with Internet Gateways. The general definition and usage patterns are also documented in Others/DevOps_Engineer_15.md.
Summary
- NAT gateways are provisioned exclusively in public subnets that have routes to an Internet Gateway.
- Private subnets access the internet by routing
0.0.0.0/0traffic to the NAT gateway ID, not directly to an IGW. - Deploy one NAT gateway per Availability Zone for high availability and to minimize data transfer costs.
- The
litu54/DevOps-Interview-Guiderepository confirms this placement pattern across multiple interview scenarios includingPersistent_Systems/DevOps_Engineer_1.mdandSigmoid/DevOps_Engineer_4.md.
Frequently Asked Questions
Can you place a NAT gateway in a private subnet?
No. A NAT gateway must reside in a public subnet with a route to an Internet Gateway. If placed in a private subnet without IGW access, the gateway would lack the necessary internet connectivity to translate addresses for outbound traffic, breaking the connection path for private instances.
How many NAT gateways should I deploy?
Deploy one NAT gateway per Availability Zone that contains private subnets. This ensures fault tolerance if an AZ fails and prevents cross-AZ data transfer charges. Each private subnet should route to the NAT gateway located in its respective AZ.
What is the difference between a NAT gateway and an Internet Gateway?
An Internet Gateway (IGW) enables bidirectional internet communication for resources with public IPs, while a NAT gateway allows only outbound internet access for resources in private subnets. The NAT gateway requires an IGW in its public subnet to function, but private instances never communicate directly with the IGW.
Do NAT gateways require Elastic IPs?
Yes. NAT gateways require an Elastic IP address (EIP) for static public IP addressing. This EIP is associated with the gateway's ENI in the public subnet, allowing return traffic from the internet to reach the gateway consistently without dynamic IP changes.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →