Why Is My NAT Gateway So Expensive?

Your NAT Gateway bill is two separate charges — a flat hourly fee and a per-GB data fee. Here's how to find the one that's hurting you and cut it.

Published July 14, 2026 · Last updated July 14, 2026

You opened Cost Explorer, grouped by usage type, and there it is: a four-figure line item for something called NatGateway-Bytes or NatGateway-Hours. You didn't change anything. Nobody spun up a new service. And yet a piece of networking plumbing you set up once and forgot about is now one of the biggest lines on your AWS bill. This post explains exactly what you're paying for, how to find the traffic that's driving it, and how to cut it — usually without breaking anything.

What am I actually paying for?

A NAT Gateway has two completely separate charges, and confusing them is why the bill feels so mysterious.

The first is an hourly charge just for existing: roughly $0.045 per hour in most US regions. That's about ~$33 per month per gateway, billed whether or not a single byte flows through it. You pay it per Availability Zone — so a "highly available" setup with one NAT Gateway in each of three AZs costs you ~$99/month before any traffic at all.

The second is a data-processing charge: roughly $0.045 per GB processed, on top of the normal data-transfer fees AWS already charges. This is the one that shocks people. Every gigabyte your private subnets send out through the gateway is metered again, purely for the privilege of passing through NAT.

If your bill is dominated by NatGateway-Hours, you probably just have more gateways than you need. If it's dominated by NatGateway-Bytes, you have a traffic problem — and that's almost always the expensive one.

Why is the data-processing charge usually the culprit?

Here's the part that catches everyone: you are paying per gigabyte to reach services that live inside AWS.

When an EC2 instance, container, or Lambda in a private subnet talks to S3, DynamoDB, ECR, CloudWatch, or almost any other AWS service, the default path is out through the NAT Gateway. From the gateway's perspective that traffic is "internet-bound," so it gets metered at ~$0.045/GB — even though the destination never actually leaves the AWS network.

Think about what that means for a real workload:

  • A data pipeline reading 2 TB/day from S3 through NAT costs roughly 2,000 GB × $0.045 = ~$90/day, or ~$2,700/month in NAT data processing alone.
  • A fleet of containers pulling large images from ECR on every deploy or scale-out event racks up per-GB charges every single pull.
  • Verbose application logs shipping to CloudWatch all day, every day, quietly metered by the gigabyte.

None of that traffic needs to touch a NAT Gateway. It's reaching AWS services that sit right next to your VPC. You're paying a toll to cross a bridge to a building on the same street.

How do I find out where the traffic is going?

Before you change anything, confirm which gateway is expensive and what's flowing through it.

Start with the CloudWatch metrics the gateway publishes. The BytesOutToDestination metric tells you how much data the gateway sent toward external destinations — the number your data-processing charge is based on. Pull the last two weeks for a specific gateway:

aws cloudwatch get-metric-statistics \
  --namespace AWS/NATGateway \
  --metric-name BytesOutToDestination \
  --dimensions Name=NatGatewayId,Value=nat-0123456789abcdef0 \
  --start-time "$(date -u -d '14 days ago' +%Y-%m-%dT%H:%M:%SZ)" \
  --end-time "$(date -u +%Y-%m-%dT%H:%M:%SZ)" \
  --period 86400 \
  --statistics Sum \
  --region us-east-1 \
  --output table

A high, steady Sum confirms the gateway is doing real work. A flat line near zero means you're paying the hourly fee for nothing (more on that below).

To find out what that traffic is, turn on VPC Flow Logs for the subnets behind the gateway. Flow logs record source, destination, and byte counts per flow, so you can see whether the top destinations are S3 prefixes, DynamoDB, ECR, or genuinely external endpoints. If the biggest talkers are AWS service IP ranges, you've found your fix.

A quick way to read them once they're flowing: send flow logs to CloudWatch Logs or S3, then use CloudWatch Logs Insights (or Athena over the S3 logs) to sum bytes grouped by dstaddr. Cross-reference the top destination IPs against the AWS IP ranges list — if the heaviest destinations map to S3, DYNAMODB, or another service's range, that traffic never needed to leave AWS and every gigabyte of it was billed by your NAT Gateway for nothing.

Should I use a gateway endpoint or an interface endpoint?

The fix for AWS-bound traffic is a VPC endpoint — a private door from your VPC directly to the service, bypassing the NAT Gateway entirely. But there are two kinds, and the difference matters to your bill.

Gateway endpoints cover S3 and DynamoDB, and they are free. No hourly charge, no per-GB charge. You add them to your route tables and the relevant traffic stops flowing through NAT immediately. For most teams, S3 and DynamoDB gateway endpoints remove the majority of the data-processing charge for zero ongoing cost. This is the single highest-leverage change you can make.

Interface endpoints (AWS PrivateLink) cover everything else — ECR, CloudWatch, Secrets Manager, SQS, and dozens more. These are not free: they bill an hourly charge per endpoint per AZ (roughly $0.01/hour, ~$7/month per AZ) plus a small per-GB fee. They're still usually cheaper than routing heavy traffic through NAT, but there's a catch.

The honest rule of thumb: add gateway endpoints for S3 and DynamoDB everywhere (they're free, so there's no downside), and add interface endpoints only where the traffic justifies the hourly cost. Then go back and delete any interface endpoints that aren't earning their keep.

When can I just delete the NAT Gateway?

Sometimes the cheapest gateway is no gateway. If a NAT Gateway's BytesOutToDestination is essentially flat zero for 14+ days, nothing in that subnet is using it — you're paying ~$33/month per AZ for a gateway that isn't moving data.

The most common way this happens: a "one NAT Gateway per AZ" template deployed for high availability into AZs that never actually received workloads. You end up with two or three gateways when one — or zero — would do. Each idle one is ~$33/month you can hand straight back.

How do I find this across my whole AWS account?

Doing this by hand for one gateway is straightforward. Doing it for every gateway, every subnet, and every unused interface endpoint across every region is where it gets tedious — and where the waste hides. That's what a scan is for. Parsivex checks each region, flags NAT Gateways whose data-processing charges could be cut with endpoints, spots interface endpoints you're paying for but not using, and estimates the monthly savings for each.

For what these findings mean once they show up in your report, see NAT Gateway overuse and Idle VPC interface endpoint, or read how scans work before you connect an account.

Related articles

Find wasted AWS spend across your whole account

Connect read-only and run a free waste scan — no credit card required. Parsivex flags idle resources, oversized instances, and networking waste in every region.

Get your free scan