AWS NAT Gateway Explained: Private Subnets, Cost & Setup
A NAT Gateway lets EC2 instances, containers, and Lambda functions in private subnets make outbound internet requests (downloading packages, calling external APIs, reaching services) without exposing those workloads to inbound internet traffic. It sits in a public subnet, holds an Elastic IP, and translates private source IPs on the way out before routing return traffic back to the correct instance. If your workloads mostly access AWS services like S3 or DynamoDB, VPC endpoints are usually a cheaper and faster alternative to routing that traffic through a NAT Gateway.
Simple explanation
Think of a NAT Gateway like a shared office reception desk. Everyone in the building (your private EC2 instances) can make outbound calls through the desk, but the outside world only ever sees the desk’s number. Calls come back to the desk, which knows who made each call and transfers the response to the right person. Your individual employees are never listed in the public directory.
The critical point: your EC2 instance does not get a public IP address. The NAT Gateway holds the Elastic IP. The internet sees the NAT Gateway’s address for every outbound connection from your private subnet. Your instance remains unreachable from the internet. It can only initiate connections outward, not receive them.
This is different from an instance in a public subnet, which has its own Elastic IP and can be reached directly. Private subnet instances trade direct internet reachability for a smaller attack surface, and use the NAT Gateway as their outbound proxy. See Default vs Custom VPCs for how VPC design decisions flow into subnet choices.
Office proxy analogy: Employees inside a building (private subnet instances) make internet requests through the front desk (NAT Gateway). The internet sees only the desk’s public address. The desk keeps track of who asked for what and routes each response back to the right person. Nobody outside the building can call an employee directly; they can only reach the desk.
How it works: traffic flow
When an EC2 instance in a private subnet makes an outbound request, here is the exact path the traffic takes:
- The EC2 instance sends a packet to an external IP (for example, a package repository or third-party API).
- The private subnet’s route table has a
0.0.0.0/0route pointing to the NAT Gateway. - The NAT Gateway receives the packet, replaces the source IP (the EC2 private IP) with its own Elastic IP, logs the connection mapping, and forwards the packet toward the Internet Gateway.
- The Internet Gateway routes the packet to the internet.
- The response returns to the Internet Gateway, is delivered to the NAT Gateway, which translates the destination back to the originating EC2 instance’s private IP and forwards it into the VPC.
Private EC2 (10.0.2.5)
|
| route: 0.0.0.0/0 -> nat-xxxxxxxx
v
NAT Gateway (public subnet, Elastic IP: 54.x.x.x)
|
| route: 0.0.0.0/0 -> igw-xxxxxxxx
v
Internet Gateway
|
v
InternetThe public subnet’s route table points 0.0.0.0/0 at the Internet Gateway. That is what makes a subnet “public.” The NAT Gateway sits inside that public subnet and uses that route to reach the internet on behalf of private instances.
Inbound connections initiated from the internet never reach the private instance. The NAT Gateway only maintains connection state for outbound-initiated sessions. This is the core security property that makes the private subnet pattern useful.
When to use a NAT Gateway
NAT Gateway is the right choice when private subnet workloads genuinely need outbound internet access:
- EC2 instances downloading OS packages or updates.
apt,yum, ordnfupdates from public repositories all require outbound internet access. - Application servers calling external APIs. Payment gateways, SaaS webhooks, and third-party data providers all require your server to initiate outbound connections.
- VPC-attached Lambda functions. Lambda loses default internet access when placed inside a VPC. A NAT Gateway restores it. See Serverless VPC Access for the full picture.
- ECS tasks and Kubernetes pods in private subnets. Containerized workloads that need to pull images from public registries or make outbound API calls follow the same routing pattern as EC2.
- Allowing a single predictable egress IP. The NAT Gateway’s Elastic IP is fixed, so external services can add it to their IP allowlists for your traffic.
When not to use a NAT Gateway
NAT Gateway is often the default answer to “how does my private subnet reach anything?”, but it is not always the right one:
- S3 and DynamoDB traffic. AWS offers free VPC Gateway Endpoints for both services. Traffic stays on the AWS network, avoids NAT processing charges, and is often lower latency. If your workload primarily reads and writes S3 or DynamoDB, setting up an endpoint is a quick win.
- Other AWS service traffic. Many AWS services support PrivateLink interface endpoints for private access without going through NAT or the internet. Services like SQS, SNS, Secrets Manager, and ECR all support this pattern.
- IPv6 outbound traffic. For instances with IPv6 addresses that need internet egress but not inbound, use an Egress-only Internet Gateway instead. NAT Gateway does not natively handle IPv6 egress (though NAT64/DNS64 exists for translating to IPv4 destinations).
- No internet access needed at all. If your workload only communicates with other AWS services via endpoints, other VPCs via peering, or on-premises via Direct Connect, you may not need a NAT Gateway. Skipping it eliminates both cost and an unnecessary egress path.
- Cross-VPC connectivity. NAT Gateway is not a tool for connecting VPCs together. Use VPC Peering or Transit Gateway for that use case.
Quick decision rule: If the destination is an AWS service, check whether a VPC endpoint exists before reaching for NAT Gateway. If the destination is a public internet address that has no AWS endpoint alternative, NAT Gateway is the right tool.
NAT Gateway vs alternatives
Several AWS constructs handle related but distinct problems. Understanding which one fits your use case avoids misrouting traffic or paying for unnecessary NAT processing.
| Option | Problem it solves | Inbound allowed? | Outbound internet? | AWS-managed? | Typical use case | Main downside |
|---|---|---|---|---|---|---|
| NAT Gateway | Private subnet outbound internet access | No | Yes (IPv4) | Yes | EC2, Lambda, containers in private subnets | Hourly + per-GB cost; one per AZ for HA |
| Internet Gateway | Public subnet two-way internet access | Yes (for instances with a public IP) | Yes | Yes | Public-facing EC2, load balancers | Instances must have a public IP; fully exposed to inbound |
| VPC Gateway Endpoint | Private access to S3 and DynamoDB | No | AWS services only | Yes | S3 and DynamoDB traffic from private subnets | Only supports S3 and DynamoDB |
| PrivateLink Interface Endpoint | Private access to other AWS services | No | AWS services only | Yes | SQS, SNS, ECR, Secrets Manager from private subnets | Per-endpoint hourly cost; one per AZ for HA |
| NAT Instance | Private subnet outbound internet access | Configurable | Yes | No (you manage the EC2) | Legacy setups; custom traffic filtering via iptables | Manual patching, scaling, and HA setup |
| Egress-only Internet Gateway | IPv6 outbound internet without inbound | No | Yes (IPv6 only) | Yes | IPv6-enabled instances needing egress-only internet | IPv6 only; does not help IPv4 workloads |
Public vs private NAT Gateway
AWS offers two connectivity modes for NAT Gateway, and they solve different problems:
Public NAT Gateway is what most teams use. It has an Elastic IP, sits in a public subnet, and provides outbound internet access for private subnet workloads. This is the standard pattern for giving private EC2 instances or Lambda functions access to the internet.
Private NAT Gateway has no Elastic IP and no internet access. It is used for private connectivity scenarios, specifically for routing traffic between VPCs or between a VPC and on-premises networks where IP address ranges overlap. If you have two VPCs that both use 10.0.0.0/16 and need to communicate, a private NAT Gateway can translate addresses to resolve the conflict.
Most teams only use public NAT Gateways. Private NAT Gateways appear in advanced hybrid connectivity architectures. If your goal is giving private subnet workloads outbound internet access, you want the public variant.
Zonal NAT Gateway vs Regional NAT Gateway
Traditionally, a NAT Gateway is an AZ-scoped resource. You create it in a specific AZ’s public subnet, and it serves traffic from private subnets in that same AZ. This is why the classic high-availability design requires one NAT Gateway per AZ. There is no automatic failover across AZs for the zonal pattern.
AWS has introduced a Regional NAT Gateway that changes this model. A Regional NAT Gateway can serve traffic from private subnets across multiple AZs within a region without requiring you to provision one gateway per AZ. AWS manages the redundancy and cross-AZ routing automatically.
The practical implication: Regional NAT Gateway simplifies the operational model (one gateway instead of three) and can reduce management overhead for architectures that do not need strict AZ-level control over their egress path. For workloads that already have multi-AZ redundancy at the application layer, Regional NAT Gateway is worth evaluating.
Check current AWS documentation for Regional NAT Gateway availability in your target region. For production workloads where you need precise control over per-AZ failure blast radius, the traditional per-AZ deployment remains a valid and well-understood choice.
Route table setup
Creating a NAT Gateway is only half the work. Without the correct route table entries, traffic from your private subnet has no path to reach it. Two route tables must be correct for end-to-end connectivity.
The public subnet where the NAT Gateway lives needs a 0.0.0.0/0 route pointing at the Internet Gateway. Without this, the NAT Gateway cannot forward traffic to the internet. The public subnet would not actually be public.
Each private subnet needs a 0.0.0.0/0 route pointing at the NAT Gateway, not the Internet Gateway. Pointing it directly at the Internet Gateway would attempt internet routing for a private instance that has no public IP, which fails silently. See Route Tables in AWS for the full explanation of how routes are evaluated.
| Subnet type | Destination | Target | Effect |
|---|---|---|---|
| Public subnet | 0.0.0.0/0 | Internet Gateway (igw-xxxxxxxx) | Enables direct internet access for public-facing resources |
| Private subnet | 0.0.0.0/0 | NAT Gateway (nat-xxxxxxxx) | Routes all external traffic through the NAT Gateway |
| Private subnet (optional) | S3 prefix list (pl-xxxxxxxx) | VPC Gateway Endpoint | Sends S3 traffic directly over the AWS network, bypassing NAT |
Easy mistake to miss: If you create a NAT Gateway but forget to update the private subnet’s route table, traffic still has no valid route and packets are dropped silently. The NAT Gateway will show as “Available” in the console and give no error. Always verify route tables after creating a NAT Gateway.
High availability and multi-AZ design
A zonal NAT Gateway is tied to a single AZ. AWS manages internal redundancy within that AZ, but if the AZ itself has a disruption, the NAT Gateway in that AZ becomes unavailable.
The failure mode to understand: if private subnets in AZ-A, AZ-B, and AZ-C all route through a single NAT Gateway in AZ-A, and AZ-A goes down, then instances in AZ-B and AZ-C lose internet access even though their own AZ is healthy. The shared NAT Gateway is a hidden availability dependency that does not show up in your EC2 or ECS health dashboards.
The correct production pattern is one NAT Gateway per AZ. Each AZ’s private route table points to the NAT Gateway in that same AZ. An AZ failure then isolates the impact. Only instances in the affected AZ lose internet access, while the other AZs continue normally.
ATM analogy: Imagine three floors of a building share a single ATM located in the basement of Floor A. If Floor A’s stairwell is blocked, nobody from Floors B or C can reach the ATM either, even though their floors are perfectly accessible. Put one ATM on each floor (one NAT Gateway per AZ) and a problem on one floor does not affect anyone else.
Cost trade-off: Three NAT Gateways cost roughly three times as much as one. For non-production environments, a single NAT Gateway is usually acceptable. For production, the added cost of per-AZ gateways is typically justified, especially when Auto Scaling launches new instances that need internet access to bootstrap.
Same-AZ NAT routing is a standard item on a well-architected networking checklist. If you are building toward highly available systems, treat it as a baseline requirement alongside multi-AZ subnets and health checks.
Cost and how to reduce it
NAT Gateway billing has two dimensions:
- Hourly charge: a fixed fee for every hour the NAT Gateway exists, whether or not traffic passes through it. In us-east-1, this is approximately $0.045/hour (around $33/month per gateway). A three-AZ production setup costs roughly $99/month in hourly charges before any data processing.
- Data processing charge: a per-GB fee for every gigabyte the gateway processes in either direction. In us-east-1, this is approximately $0.045/GB. For workloads with high throughput (frequent container image pulls, large file downloads, streaming data), this becomes the dominant line item.
Cross-AZ transfer cost catches teams off guard. If instances in AZ-B route through a NAT Gateway in AZ-A, you pay cross-AZ transfer charges on top of NAT processing fees. This is invisible until you see the bill. Matching NAT Gateways to their AZ eliminates it entirely. See Network Egress Costs Explained for the full breakdown.
Cost-reduction strategies:
- VPC Gateway Endpoints for S3 and DynamoDB. Free to create. Traffic to these services no longer passes through the NAT Gateway, eliminating all processing charges for that traffic. For workloads that read and write S3 heavily, this is typically the highest-leverage change.
- PrivateLink interface endpoints for other AWS services. ECR, SQS, SNS, Secrets Manager, and many others support private endpoints. Each has its own hourly cost, so evaluate whether the traffic volume makes the trade worthwhile.
- Cache dependencies locally. Pulling the same container image or package multiple times through NAT multiplies the data processing charge. Push images to ECR and use package mirrors or caching proxies inside the VPC.
- Same-AZ routing. Eliminating cross-AZ NAT traffic removes both the cross-AZ transfer charge and reduces unnecessary NAT processing volume.
- Delete unused gateways. NAT Gateways in dev and test environments charge hourly with zero traffic. Delete them when not needed, or automate shutdown outside business hours.
Start here if your NAT costs are surprising: Check whether S3 or DynamoDB traffic is flowing through NAT Gateway. In CloudWatch, look at the BytesOutToDestination metric. Add a free VPC Gateway Endpoint for S3 if it is. This single change commonly cuts NAT bills by 30 to 60 percent for data-heavy workloads.
Common mistakes
- Placing the NAT Gateway in a private subnet. The NAT Gateway must be in a public subnet, one with a route to the Internet Gateway. A NAT Gateway in a private subnet has no path to the internet and will not forward traffic.
- Forgetting to update the route table. Creating the NAT Gateway does nothing until the private subnet’s route table has a
0.0.0.0/0entry pointing at the gateway ID. This is the most common reason NAT setups appear to silently fail. - Assuming the EC2 instance gets a public IP. It does not. Only the NAT Gateway holds the Elastic IP. Your private instance remains unreachable from the internet.
- Using one NAT Gateway for a multi-AZ production VPC. If the AZ hosting your shared NAT Gateway goes down, all private subnets in other AZs also lose internet access. Use one NAT Gateway per AZ in production, and point each AZ’s private route table at the local gateway.
- Routing S3 and DynamoDB traffic through NAT. VPC Gateway Endpoints for both services are free and keep traffic on the AWS network. Routing this through a NAT Gateway adds per-GB charges for no benefit.
- Leaving NAT Gateways running in dev environments. A forgotten dev NAT Gateway costs around $33/month in hourly charges alone, with zero traffic. Add cleanup reminders or automate deletion for non-production environments.
- Pointing the wrong route table at NAT Gateway. In a VPC with multiple private subnets across AZs, it is easy to update the wrong route table association. Verify each subnet’s route table after making changes. Use the network troubleshooting guide if routing behaves unexpectedly.
NAT Gateway vs NAT instance
Before NAT Gateway existed, the only option was running an EC2 instance configured to perform NAT. NAT Gateway replaced this pattern for most teams because it is managed, scales automatically, and requires no OS maintenance.
| Feature | NAT Gateway | NAT Instance |
|---|---|---|
| Management | Fully managed by AWS | You manage the EC2 instance |
| Availability | Highly available within one AZ | Single EC2; single point of failure unless you build redundancy manually |
| Throughput | Scales automatically (up to 100 Gbps) | Capped by instance type; a t3.small tops out quickly under load |
| Security groups | Not applicable | Must configure security groups on the instance |
| OS patching | AWS handles it | You patch the OS and manage updates |
| Baseline cost | Higher hourly charge | Lower if using a small instance, but you absorb operational overhead |
| Custom traffic filtering | Not supported | Can use iptables to restrict which destinations are reachable |
The only scenario where a NAT instance makes practical sense today is when you need custom iptables rules at the NAT layer, for example an allowlist of permitted external destinations for compliance reasons. Even then, AWS Network Firewall is usually a cleaner and more maintainable solution. For new architectures, NAT Gateway is the default.
How to create a NAT Gateway
These steps assume you have a VPC with at least one public subnet and an Internet Gateway already attached. You will need the subnet ID of your public subnet and the route table ID of your private subnet.
# 1. Allocate an Elastic IP for the NAT Gateway
aws ec2 allocate-address --domain vpc
# Note the AllocationId from the output (eipalloc-...)
# 2. Create the NAT Gateway in your public subnet
aws ec2 create-nat-gateway \
--subnet-id subnet-YOUR_PUBLIC_SUBNET \
--allocation-id eipalloc-YOUR_ALLOC_ID
# Note the NatGatewayId from the output (nat-...)
# 3. Wait until the gateway is available (~1 minute)
aws ec2 wait nat-gateway-available \
--nat-gateway-ids nat-YOUR_NAT_ID
# 4. Add the default route to your private subnet's route table
aws ec2 create-route \
--route-table-id rtb-YOUR_PRIVATE_ROUTE_TABLE \
--destination-cidr-block 0.0.0.0/0 \
--nat-gateway-id nat-YOUR_NAT_IDFor a multi-AZ setup, repeat all four steps for each AZ: a separate Elastic IP, a separate NAT Gateway in that AZ’s public subnet, and a separate route table update for that AZ’s private subnet.
Summary
- A NAT Gateway gives private subnet workloads outbound internet access without exposing them to inbound connections or assigning them a public IP.
- It must be placed in a public subnet and requires an Elastic IP. The private subnet’s route table must point
0.0.0.0/0at the NAT Gateway ID, not the Internet Gateway. - For S3 and DynamoDB traffic, use free VPC Gateway Endpoints instead. For other AWS services, consider PrivateLink interface endpoints to avoid routing through NAT entirely.
- For production, deploy one NAT Gateway per AZ to prevent a single AZ failure from cutting internet access for the entire VPC.
- NAT Gateway billing is hourly plus per-GB processed. Same-AZ routing, VPC endpoints, and local dependency caching are the main cost levers.
- NAT instances are largely obsolete except in niche scenarios requiring custom traffic filtering at the NAT layer.
Frequently asked questions
Does a NAT Gateway give my EC2 instance a public IP address?
No. Your EC2 instance keeps its private IP. The NAT Gateway holds the Elastic IP. From the internet, all outbound traffic from your private subnet appears to originate from the NAT Gateway's Elastic IP, so your instance is never directly addressable from the internet.
Do I need one NAT Gateway per Availability Zone?
Yes, for production workloads. A NAT Gateway is scoped to a single AZ. If you route multiple AZs through one NAT Gateway and that AZ has an outage, all private subnet instances lose internet access. Create one per AZ, and point each AZ's private route table at the local NAT Gateway.
What is the difference between a NAT Gateway and an Internet Gateway?
An Internet Gateway (IGW) provides bidirectional connectivity: instances with public IPs can receive inbound traffic directly from the internet. A NAT Gateway provides outbound-only access for instances that have no public IP. You need both: the NAT Gateway sits in a public subnet and uses the Internet Gateway to reach the internet.
Can Lambda in a VPC use a NAT Gateway for internet access?
Yes. When you attach a Lambda function to a VPC, it loses default internet access. Route its subnet through a NAT Gateway in the same VPC to restore outbound internet connectivity. The Lambda function runs in a private subnet and traffic flows through the NAT Gateway exactly as it does for EC2.
How can I reduce NAT Gateway cost?
Three main levers: use free VPC Gateway Endpoints for S3 and DynamoDB so traffic never touches the NAT Gateway; place one NAT Gateway per AZ to eliminate cross-AZ data transfer charges; cache container images in ECR and dependencies locally to reduce the volume of data processed.
What is a private NAT Gateway?
A private NAT Gateway has no Elastic IP and no internet access. It is used for connectivity between VPCs or on-premises networks with overlapping IP ranges, not for internet egress. Most teams only encounter public NAT Gateways unless they are building complex hybrid network topologies.