NAT Gateways are one of the most reliable line items on an AWS bill for a simple reason: they charge for existing, not for being used well. Every NAT Gateway bills an hourly uptime rate plus a per-GB data processing fee on top of standard data transfer — and neither of those charges cares whether the traffic passing through it was necessary.
What you're actually paying for
A NAT Gateway has two charges: an hourly charge for the gateway existing, and a per-GB charge for every gigabyte it processes — in both directions. Check AWS's current pricing page for your region, but the shape of the bill is consistent: the hourly charge is fixed and small, the per-GB charge is where accounts with real egress volume get surprised. A service moving a few terabytes a month through a NAT Gateway can rack up more in data processing fees than the gateway's uptime cost for the entire month.
Multiply that by three — one NAT Gateway per Availability Zone, which is the standard, correct pattern for high-availability architectures — and you're paying that per-GB rate three times over on a well architected but under-examined VPC.
The traffic that doesn't need to be there
The most common source of avoidable NAT Gateway spend isn't the redundancy — it's private subnet resources reaching AWS services (S3, DynamoDB, ECR, Secrets Manager, and others) through the NAT Gateway when they don't have to. That traffic is routable entirely within AWS's network via VPC endpoints, and never needs to touch a NAT Gateway at all.
Same traffic, two paths — one priced per GB through a NAT Gateway, one free through a Gateway Endpoint.
- Gateway endpoints (S3, DynamoDB) are free and route traffic to those two services without a NAT Gateway in the path at all.
- Interface endpoints (most other AWS services) have their own hourly + per-GB cost, but that cost is typically well below what the same traffic costs routed through a NAT Gateway, especially at volume.
If a private subnet is talking to S3 constantly — for logs, backups, artifact pulls, CUR delivery, whatever — and there's no S3 Gateway Endpoint attached to that subnet's route table, that traffic is paying the NAT Gateway tax for no reason.
Finding it
Cost Explorer, filtered to the NAT Gateway usage type, will show the trend and let you see which direction it's moving. To find the source, VPC Flow Logs on the NAT Gateway's elastic network interface will show you exactly which resources are generating the traffic and where it's headed — that's usually enough to spot "this is all S3 traffic" or "this is one chatty service talking to an external API" within a few minutes of reading.
What actually fixes it
- Add Gateway Endpoints for S3 and DynamoDB if they're missing — this is close to a five-minute change with no application code changes required.
- Add Interface Endpoints for other high-volume AWS service traffic once you've confirmed the volume justifies the endpoint's own hourly cost.
- Reconsider one-NAT-Gateway-per-AZ only if the workload genuinely doesn't need multi-AZ resilience — for most production workloads, this isn't the fix; routing unnecessary traffic around the NAT Gateway is.