DEV Community

Cover image for Why your NAT gateway bill keeps growing (and the 20 minute fix)
Neeraj Sharma
Neeraj Sharma

Posted on AI-assisted

Why your NAT gateway bill keeps growing (and the 20 minute fix)

If your workloads run in private subnets, a big part of your NAT gateway bill is probably traffic to S3. The fix takes a few minutes and costs nothing.

NAT gateway pricing in us-east-1 is $0.045 per hour plus $0.045 per GB processed. The hourly part is small. The per-GB part grows with every image pull, backup and log upload that leaves a private subnet.

S3 traffic path from a private subnet, through a NAT gateway versus an S3 gateway endpoint

Check if this is you

In Cost Explorer, filter Service to "EC2-Other" and group by Usage Type. Look for NatGateway-Bytes. In us-east-1 it has no prefix; other regions get one, like USW2-NatGateway-Bytes. If it's near the top, keep reading.

To see where the bytes go, turn on VPC Flow Logs for the NAT gateway's network interface and sum bytes by destination. If most destinations fall in the S3 ranges from ip-ranges.amazonaws.com/ip-ranges.json, you found it.

Fix 1: S3 and DynamoDB gateway endpoints (free)

Gateway endpoints for S3 and DynamoDB have no hourly or data charge. Create one and attach your private route tables:

aws ec2 create-vpc-endpoint \
  --vpc-id vpc-0abc123 \
  --vpc-endpoint-type Gateway \
  --service-name com.amazonaws.us-east-1.s3 \
  --route-table-ids rtb-0priv1 rtb-0priv2
Enter fullscreen mode Exit fullscreen mode

It only covers buckets in the same region. Creating it drops open TCP connections to S3, so don't do it mid-backup, and check that your clients reconnect. S3 will also see your private IPs instead of the NAT's public IP, so bucket policies that allow by source IP need updating. ECR pulls get cheaper too, because image layers are served from S3.

Fix 2: interface endpoints, but only above break-even

ECR API, STS, CloudWatch Logs and most other services need interface endpoints instead. These are not free: $0.01 per hour per AZ plus $0.01 per GB. Across two AZs that is $14.60 a month (2 x 730 hours x $0.01) before any traffic.

Every GB you move off NAT saves $0.035 ($0.045 minus $0.01). So one endpoint in two AZs pays for itself at about 420 GB a month. Below that, leave the traffic on NAT.

Monthly cost of NAT processing versus an interface endpoint in two AZs, break-even at about 417 GB

Fix 3: watch cross-AZ traffic to the NAT

With one NAT gateway for the whole VPC, traffic from the other AZs pays inter-AZ transfer just to reach it: $0.01/GB in each direction, so $0.02 for every GB that crosses. A second NAT gateway costs about $33 a month in hours, so it pays off once roughly 1.6 TB a month crosses from that AZ.

Do fix 1 first. It's free and it's usually the biggest chunk.

The full list of leaks I check (NAT, egress, idle EBS, public IPv4 and more) is in this AWS cost optimization checklist, and there's a free cloud cost calculator if you want to plug in your own numbers.

Prices are us-east-1 list prices.

Top comments (1)

Collapse
 
dhruv_malaviya_cdcc71e595 profile image
Dhruv Malaviya •

Fix 1 is the right call, and "don't do it mid-backup" is the detail most write-ups skip.

Worth naming why this class of bill exists at all: it's a consequence of the VPC shape, not of AWS being expensive. Private subnets have no egress path, so you buy one, then pay per GB to use it. Gateway endpoints are free because that traffic stops leaving.

That's the tradeoff we made the other way at Krova Cloud , no VPCs, no subnets, no security groups, no NAT. A Cube has outbound access by default and bandwidth is unmetered, so there's no per-GB line to optimise.

The cost of that choice is real: no subnet-level segmentation and no security groups. If your architecture depends on those, this doesn't apply.

One caveat we publish rather than bury — sustained heavy transfer is subject to our AUP, and public mirrors or media relays need prior approval.