Short answer: a NAT Gateway charges twice: once per hour it exists and again for every GB it processes. If workloads in private subnets talk to S3 or DynamoDB through it, you pay for traffic that a free gateway endpoint would carry instead.
- Time
- 40 min
- Cost
- ≈ US$ 1
- Level
- Intermediate
- Services
- VPC · NAT · S3
How NAT Gateway billing works
In us-east-1, the public price is US$ 0.045 per hour per NAT Gateway and US$ 0.045 per GB processed, in either direction. Data transfer charges (for example to the internet or across AZs) come on top. Prices vary by region, so check the VPC pricing page for yours.
One NAT Gateway running all month (730 hours × US$ 0.045), before any GB is processed. One gateway per AZ for high availability multiplies this.
The hourly part is predictable. The per-GB part is where bills surprise people: pulling container images, writing logs or reading objects from S3 through the NAT all count as processed bytes.
Step 1: Confirm the NAT is the expensive line
Group your cost by usage type and look for entries ending in NatGateway-Bytes and NatGateway-Hours. The prefix changes by region (for example USE1-).
cost-by-usage-type.sh
aws ce get-cost-and-usage \
--time-period Start=2026-09-01,End=2026-10-01 \
--granularity MONTHLY --metrics UnblendedCost \
--group-by Type=DIMENSION,Key=USAGE_TYPE \
--query 'ResultsByTime[0].Groups[?contains(Keys[0], `NatGateway`)]' \
--output table
Step 2: Find what the NAT is talking to
Enable VPC Flow Logs on the NAT Gateway network interface and look at the destinations with the most bytes. If the top destinations are S3 or DynamoDB IP ranges, the fix is cheap. If they are external APIs or package mirrors, you need a different strategy (caching, a proxy, or keeping the NAT).
Step 3: Move S3 and DynamoDB traffic to gateway endpoints
Gateway endpoints for S3 and DynamoDB have no hourly or per-GB charge. They are added to route tables, so traffic from those subnets stops going through the NAT.
create-s3-gateway-endpoint.sh
aws ec2 create-vpc-endpoint \
--vpc-id vpc-0abc1234 \
--service-name com.amazonaws.us-east-1.s3 \
--route-table-ids rtb-0private1 rtb-0private2
Interface endpoints (PrivateLink) are not free: they charge per hour per AZ and per GB. They still make sense for services like ECR or CloudWatch Logs when the NAT traffic to them is large, but do the math first.
NAT Gateway vs VPC endpoints
| Option | Hourly (us-east-1) | Per GB | Use it for |
|---|---|---|---|
| NAT Gateway | US$ 0.045 | US$ 0.045 processed | Internet egress from private subnets |
| Gateway endpoint (S3, DynamoDB) | US$ 0 | US$ 0 | S3 and DynamoDB from private subnets |
| Interface endpoint | US$ 0.01 per AZ | US$ 0.01 (first PB) | Other AWS APIs with heavy traffic |
Prevent it from coming back
- Create the S3 and DynamoDB gateway endpoints in your VPC module, so every new VPC has them.
- Set an AWS Budgets alert on the
NatGateway-Bytesusage type. - Turn on Cost Anomaly Detection for EC2-Other, where NAT charges show up.
Prices above are the public us-east-1 list prices at the time of writing. Check the pricing page before you rely on them.
Run the numbers for your account
Use the NAT Gateway vs VPC endpoints calculator with your own traffic and prices.