Key takeaways
- A NAT gateway costs about $33 a month before it moves a single byte, then $0.045 per GB processed
- S3 and DynamoDB traffic through a NAT gateway is pure waste: gateway endpoints carry it free
- An interface endpoint pays for itself once a service pushes about 7 GB a day through NAT in one AZ
- Check the data-processing line, not the hourly line; that is where NAT bills explode
The NAT gateway is one of the most quietly expensive components in a standard VPC design. It does exactly what it promises, and it bills exactly as documented: an hourly charge for existing and a per-gigabyte charge for everything it touches. The problem is that almost nobody reads the second charge until it is large, and by the time it is large, the traffic patterns behind it feel too load-bearing to question. This guide walks the five steps we use to shrink it.
Find what your NAT gateways actually cost
NatGateway-Bytes usage type rather than anywhere obvious, which is why a $40 estimate becomes a $700 line item without anyone noticing the transition.NatGateway-Hours and NatGateway-Bytes, then group by resource to see each gateway individually. Two patterns are worth flagging immediately.The first is a single gateway processing terabytes. That means one workload is routing bulk traffic through it, and finding that workload is step two. At 10 TB a month, the processing charge alone is roughly $460, which is usually more than the compute generating the traffic.
The second is the opposite: many gateways each costing almost exactly $33 a month, the signature of the one-NAT-gateway-per-AZ default applied to every VPC in every environment. Three AZs across four environments is twelve gateways, $394 a month, before a single byte moves. High availability is the right call for production; whether the QA environment needs three redundant gateways is a fair question that nobody asked at setup time.
Map the traffic behind the biggest gateway
VPC Flow Logs on the NAT gateway's elastic network interface tell you where the bytes go. Enable them to CloudWatch Logs or S3 if they are not already on, give them a day or two to accumulate, and aggregate by destination. In CloudWatch Logs Insights, against the gateway's ENI:
filter interfaceId = 'eni-0123456789abcdef0'
| stats sum(bytes) as totalBytes by dstAddr
| sort totalBytes desc
| limit 25
Resolve the top destinations and you will almost always find the same suspects: S3 transfers, DynamoDB access, container-image pulls from ECR, CloudWatch Logs ingestion, and calls to other AWS APIs. All of that is AWS-internal traffic paying retail NAT rates to leave and re-enter the network, the cloud equivalent of paying international roaming charges to call the house next door. It is common for well over half of a busy gateway's bytes to be traffic to AWS's own services, and every one of those bytes has a cheaper path.
Route S3 and DynamoDB through gateway endpoints
Gateway VPC endpoints for S3 and DynamoDB are free. No hourly charge, no per-gigabyte charge, no capacity to manage. Adding one is a route-table entry: the endpoint installs a prefix-list route in the subnets you attach it to, and from that moment traffic from private subnets to that service stops touching the NAT gateway entirely. No application change, no DNS change, no downtime.
This is the highest-ratio fix in this guide: a workload syncing 5 TB a month to S3 through a NAT gateway pays about $225 a month in processing for traffic a gateway endpoint carries for nothing. The change takes minutes, and the only real prerequisite is checking that nothing depends on the traffic exiting with a public IP, which is rare.
If there is one action to take from this article, it is this one. There is no workload shape for which S3 or DynamoDB traffic through a NAT gateway is the right answer.
Reprice the remaining paths with interface endpoints
For the other AWS services in your flow-log top list, interface endpoints are the option: $0.01 per hour per AZ (about $7.30 a month each) plus $0.01 per gigabyte processed, against the NAT gateway's $0.045 per gigabyte.
The arithmetic per service and AZ: an interface endpoint saves $0.035 on every gigabyte but adds $7.30 a month of standing cost, so it breaks even near 210 GB a month, roughly 7 GB a day. Anything pushing more than that through NAT is cheaper on an endpoint; anything well under it is cheaper staying on the gateway. ECR (image pulls), CloudWatch Logs (agent ingestion), and Secrets Manager are the usual first candidates in container-heavy environments; a cluster that pulls a few gigabytes of images per deploy, many times a day, clears the threshold easily.
Whatever remains after endpoints is genuine internet egress. That traffic belongs on a NAT gateway, but two structural questions remain. First, do dev and staging VPCs each need their own gateway per AZ, or can a consolidated egress VPC (via Transit Gateway) serve them at a fraction of the idle cost? Second, is anything crossing availability zones to reach its gateway? Traffic from an instance in one AZ to a NAT gateway in another pays inter-AZ transfer on top of NAT processing, which is the expensive version of a topology mistake: either align subnets to their local gateway or accept the documented premium deliberately.
Verify the drop and set a guardrail
NatGateway-Bytes line should already show the change. Compare a full week against the prior baseline: the S3 and DynamoDB share of processed bytes should be gone, and the remaining volume should match your genuine internet egress.NatGateway-Bytes usage type, set a comfortable margin above the new baseline, costs nothing and catches the next workload that quietly starts routing bulk traffic through the gateway. The failure mode this guide fixes is silence; the guardrail's job is to make sure the second occurrence is loud.


