You've built a solid VPC architecture, deployed your microservices, and everything's working smoothly—until your AWS bill lands and you see a line item that makes your stomach drop. NAT Gateway charges can surprise even experienced teams because they operate on a deceptive pricing model: you pay an hourly fee and a per-gigabyte data processing charge. The NAT Gateway cost trap: practical tips and trade-offs isn't about avoiding NAT Gateways entirely; it's about understanding when they're truly necessary, measuring what's actually flowing through them, and using the right AWS endpoints to cut waste.
Understanding the dual pricing model
A NAT Gateway costs roughly $0.032 per hour (varies by region) plus $0.045 per GB of data processed. On the surface, that seems reasonable. In practice, teams often don't realize how quickly gigabytes accumulate, especially when they're not monitoring traffic closely.
Consider a typical scenario: you have three availability zones, each with a public subnet containing a NAT Gateway. If each NAT Gateway processes just 100 GB per month (a conservative estimate for many teams), you're looking at roughly $135 per NAT Gateway monthly just for data processing, plus another $23 per hour per NAT Gateway. Three NAT Gateways across AZs means you're easily spending $500–$800 per month before you've even scaled.
The real trap isn't the NAT Gateway itself—it's that most traffic flowing through them shouldn't be there at all. Private resources should access AWS services privately whenever possible, and public resources should use efficient routing patterns. Many teams discover this only after reviewing their first substantial AWS bill.
Hourly plus per-GB: You pay to process every byte that passes through
The pricing structure is straightforward but requires discipline to manage. You're charged:
- Hourly rate: Whether you process 1 GB or 1 TB, you pay for every hour the NAT Gateway is provisioned. Even idle NAT Gateways cost money.
- Data processing: Every gigabyte of traffic—inbound or outbound—incurs a per-GB charge. This includes DNS lookups, API calls, and large file transfers.
To illustrate, suppose you're running an ECS service in a private subnet that needs to pull Docker images from Docker Hub during deployments. If your image is 500 MB and you deploy 10 times per month, that's 5 GB of traffic through the NAT Gateway each month. Multiply that across your entire team's services and you're quickly at 50–100 GB monthly.
Now add routine operations: pulling dependencies from npm or pip, making API calls to third-party services, and periodic backups. The charges compound fast. Many teams don't segment their NAT Gateways by workload type, so all traffic—critical and routine—flows through the same expensive gateway.
Pro tip: If you provision a NAT Gateway and it sits idle, you're still paying the hourly fee. Conversely, deleting a NAT Gateway immediately stops the hourly charge, even mid-hour in most regions. This matters for environments you don't always need.
Common culprits: Pulling images, S3 traffic and API calls to AWS services
Understanding what actually drives your bill is the first step to controlling it. Here are the biggest offenders:
Container image pulls
Every time an ECS task, Lambda, or EC2 instance in a private subnet pulls an image from Docker Hub, Amazon ECR, or any registry, that traffic routes through your NAT Gateway. A single 400 MB image pull costs roughly $0.018 at current rates, but if you deploy frequently or auto-scale, you'll pull dozens of images daily.
S3 downloads and uploads
Private EC2 instances or Lambda functions that read or write to S3 without using a VPC endpoint are incurring NAT Gateway charges. This is especially wasteful because you can route S3 traffic entirely within AWS's network for free using a Gateway endpoint.
API calls to AWS services
Any API call to services like DynamoDB, SNS, SQS, Secrets Manager, or Systems Manager from a private subnet without an endpoint is taxing your NAT Gateway. Even small JSON payloads add up when you're making thousands of calls per second.
Database replication and backups
If your RDS instance or other managed service is sending data across subnets or availability zones without proper routing, or if you're pulling large backups from S3, the NAT Gateway may be in the path. This is often overlooked in cost audits.
Third-party API calls and webhooks
Any outbound call to external APIs, payment processors, or monitoring services will route through the NAT Gateway. If you're making thousands of requests per day to external services, those bytes add up quickly.
Fixes: Gateway endpoints for S3, interface endpoints and ECR pull-through caches
The good news is that you have multiple tools to bypass or reduce NAT Gateway dependency. Each has trade-offs, and combining them effectively is where cost optimization happens.
Gateway endpoints for S3 and DynamoDB
A Gateway endpoint is a VPC endpoint that allows private resources to access S3 and DynamoDB without leaving the AWS network. It's free and requires only a route table update.
# Create a Gateway endpoint for S3
aws ec2 create-vpc-endpoint \
--vpc-id vpc-12345678 \
--service-name com.amazonaws.us-east-1.s3 \
--route-table-ids rtb-abcdef01 \
--policy-document file://s3-endpoint-policy.json
After provisioning, add a route table entry that directs S3 traffic to the endpoint. Your EC2 instances, Lambda functions, and ECS tasks now access S3 without touching the NAT Gateway. The cost savings are immediate and often substantial. For most teams, a Gateway endpoint for S3 pays for itself within hours.
Interface endpoints for other services
Interface endpoints use PrivateLink to expose AWS services (and third-party services) inside your VPC. Unlike Gateway endpoints, they cost roughly $7 per month per AZ plus $0.01 per GB processed, making them economical only for high-traffic services.
Interface endpoints make sense for:
- Secrets Manager: If your applications fetch secrets frequently, an interface endpoint eliminates repeated NAT Gateway traffic.
- Systems Manager Parameter Store: Similar to Secrets Manager; high-call-volume applications benefit significantly.
- SNS, SQS, and Kinesis: If you're in a private VPC and communicate with these services often, an endpoint is cheaper than NAT Gateway traffic.
# Create an interface endpoint for Secrets Manager
aws ec2 create-vpc-endpoint \
--vpc-id vpc-12345678 \
--vpc-endpoint-type Interface \
--service-name com.amazonaws.us-east-1.secretsmanager \
--subnet-ids subnet-12345678 subnet-87654321
The break-even point depends on your region and data volume, but for services with consistent, high-volume traffic, interface endpoints pay for themselves quickly.
ECR pull-through cache
If you're regularly pulling images from Docker Hub or other public registries, an ECR pull-through cache repository acts as a local mirror within AWS. The first pull still goes through the NAT Gateway, but subsequent pulls are cached in your private ECR, eliminating redundant external traffic.
# Create a pull-through cache repository for Docker Hub
aws ecr create-pull-through-cache-repository \
--ecr-repository-prefix docker-hub \
--upstream-repository-url docker.io
This approach is particularly effective for teams that deploy the same base images repeatedly. Over time, the NAT Gateway savings compound as cache hit rates improve.
NAT instance as an alternative
For lower-traffic scenarios, a NAT instance (a regular EC2 instance configured to route traffic) can be cheaper than a NAT Gateway. NAT instances use standard EC2 pricing, which may be lower depending on your traffic pattern. However, NAT instances require more operational overhead: you must manage patching, security groups, and high availability. Most teams find NAT Gateways worthwhile despite higher list price, but if your traffic is genuinely light, a NAT instance deserves evaluation.
Measure first: VPC Flow Logs show who sends the traffic
Before optimizing, you must understand what's actually flowing through your NAT Gateways. VPC Flow Logs capture metadata about every packet traversing your VPC, including source, destination, protocol, and byte count. This data is your foundation for cost optimization.
# Enable VPC Flow Logs to CloudWatch
aws ec2 create-flow-logs \
--resource-type VPC \
--resource-ids vpc-12345678 \
--traffic-type ALL \
--log-destination-type cloud-watch-logs \
--log-group-name /aws/vpc/flowlogs \
--deliver-logs-permission-role-arn arn:aws:iam::ACCOUNT_ID:role/flowlogsRole
Once Flow Logs are running (they incur a small CloudWatch Logs cost), query them to identify top traffic sources and destinations:
# Example: Find top destinations by bytes (using CloudWatch Logs Insights)
fields srcaddr, dstaddr, srcport, dstport, bytes
| stats sum(bytes) as total_bytes by dstaddr
| sort total_bytes desc
| limit 20
With this data in hand, you can make informed decisions: which workloads genuinely need outbound internet access via NAT, which could use an endpoint, and which might benefit from an interface endpoint or caching layer.
Many teams discover that 60–80% of their NAT Gateway traffic could be eliminated with proper endpoint configuration. That's not speculation; it's measurable fact once you enable Flow Logs.
Common mistakes
- Provisioning multiple NAT Gateways without measuring traffic first. Three NAT Gateways for high availability make sense once you've validated they're necessary, but many teams provision them reflexively. Start with one per AZ, measure, then add more if needed.
- Forgetting that ENI attachments incur charges. NAT Gateways use Elastic Network Interfaces (ENIs), which add a small hourly cost on top of the NAT Gateway fee. This isn't huge, but it compounds with multiple gateways.
- Not using Gateway endpoints for S3 and DynamoDB. This is low-hanging fruit. If you're using these services from a private VPC, you're leaving money on the table by not using free Gateway endpoints.
- Deploying interface endpoints for low-traffic services. An interface endpoint for a service you call once per day is more expensive than routing through a NAT Gateway. Measure and calculate before deploying.
- Ignoring cross-AZ traffic. Data moving between AZs within your VPC also incurs charges (though not NAT Gateway charges specifically, it's related overhead). This is another reason to architect carefully and measure.
Key takeaways
- NAT Gateways charge both hourly and per-gigabyte; the per-GB cost is what surprises most teams because traffic is often invisible until you measure it.
- Enable VPC Flow Logs immediately to baseline your traffic patterns and identify optimization opportunities with hard data.
- Deploy Gateway endpoints for S3 and DynamoDB first—they're free and often eliminate 30–50% of NAT Gateway traffic in typical workloads.
- Evaluate interface endpoints for high-volume AWS service calls, but calculate the break-even point (roughly 160 GB per month per AZ at current pricing) before provisioning.
- Consider ECR pull-through caches if you repeatedly pull public container images; the initial pull costs the same, but cache hits eliminate external traffic entirely.
- Start with one NAT Gateway per AZ for high availability, then scale only after proving traffic demand. Removing unused gateways immediately stops hourly charges.
- Review NAT Gateway costs quarterly as part of cost optimization reviews; what makes sense at small scale may not at scale, and new endpoints or caching strategies may have become cost-effective.






Comments
Loading comments…