AWS NAT Gateway Cost: What You Actually Pay For
NAT Gateway bills two separate ways, and almost everyone optimises the wrong one. There is an hourly charge for each gateway you run, and a per-gigabyte charge for every byte that passes through it. Teams see the line item, assume it is the hourly cost, and start consolidating gateways across availability zones - which saves a little and quietly introduces cross-AZ transfer charges that can cost more than the gateways did.
In most accounts I audit, the per-gigabyte half is the larger number, and a meaningful share of it is traffic that had no business crossing a NAT Gateway at all.
Short answer: in us-east-1 a NAT Gateway costs $0.045 per hour (about $32 a month) plus $0.045 per GB it processes, plus a small charge for its public IPv4 address. At any real volume the per-GB charge dominates, and much of it is usually S3 and DynamoDB traffic that a free VPC gateway endpoint takes off the NAT entirely.
If you want your own figure before reading further, the NAT Gateway cost calculator takes your gateway count and monthly gigabytes and splits the bill into its parts.
The two charges, and which one is your problem
Current us-east-1 rates, from Amazon VPC pricing:
- Hourly: $0.045 per NAT Gateway per hour - roughly $32/month per gateway, billed whether or not a single byte moves.
- Processing: $0.045 per GB passing through the gateway, in either direction.
The public IPv4 address attached to each public NAT Gateway is also billed hourly, like any public IPv4 address - a few dollars a month per gateway. Rates vary by region; check the pricing page for yours.
The ratio is what matters. At 1 TB/month through one gateway you pay about $32 hourly and about $45 processing - comparable. At 20 TB/month the processing charge is roughly 28 times the hourly charge, and consolidating gateways is irrelevant to your bill.
So the first thing to establish is the split. If processing dominates, every hour spent on gateway topology is wasted; the work is in reducing gigabytes. If hourly dominates, you are running gateways for subnets that barely egress, and the question is whether they need to exist.
The hidden part: in-region traffic is not free
The per-gigabyte processing charge applies to everything traversing the gateway - including traffic to other AWS services in the same region.
This catches people out constantly, because the mental model is "data transfer within a region is free." That is true of some paths and emphatically not true of this one. An EC2 instance in a private subnet pulling 5 TB from an S3 bucket in the same region pays NAT processing on all 5 TB, even though S3 is metres away in the same data centre.
Which leads to the single most common avoidable item I find.
The S3 and DynamoDB mistake
A VPC Gateway Endpoint for S3 or DynamoDB costs nothing. No hourly charge, no per-gigabyte charge. It adds a route so that traffic to those two services leaves your private subnet directly instead of going out through NAT.
If you have not created them, every byte your workloads read from or write to S3 and DynamoDB is being billed NAT processing for no reason whatsoever. For data-heavy workloads - ETL, log shipping, backups, container images pulled from an S3-backed registry, anything with a Spark or analytics tier - this is routinely the largest single line item that can be removed outright, with no architectural change and no performance cost. It is strictly faster as well as cheaper, because the traffic takes a shorter path.
Two caveats worth knowing:
- Gateway endpoints only cover S3 and DynamoDB. Every other service needs an Interface endpoint (PrivateLink), which has its own hourly and per-gigabyte charges. Those are often still cheaper than NAT for high-volume services, but they are not free, so they need arithmetic rather than assumption.
- Gateway endpoints are regional and route-table scoped. Creating one is not enough; it has to be associated with the route tables your private subnets actually use. A half-applied endpoint silently leaves some subnets on the NAT path, which is exactly the kind of thing that looks fixed and is not.
How to find your avoidable gigabytes
Do not guess at this. Measure it, then decide.
- Enable VPC Flow Logs on the subnets behind the gateway, if they are not on already.
- Query for traffic whose destination is an AWS service prefix - S3 and DynamoDB first. Athena over Flow Logs in S3 is the usual route. You are looking for bytes leaving private subnets toward AWS-owned address ranges, which are published as AWS-managed prefix lists.
- Total those bytes and multiply by the per-GB rate. That number is your monthly saving from gateway endpoints, and it requires no trade-off to capture.
- Then look at what is left. Genuine internet egress - package installs, third-party APIs, webhooks - is the irreducible part. Large and surprising volumes here usually mean an unpinned dependency pulling on every build, or a container image being fetched from a public registry on every pod start rather than cached.
Step 4 is where teams find their second-largest item, and it is almost never visible from Cost Explorer alone, because Cost Explorer tells you the gateway processed 14 TB and nothing about what was in it.
The cross-AZ trap
The textbook high-availability pattern is one NAT Gateway per availability zone, with each AZ's private subnets routing to their local gateway. It costs more in hourly charges and it is correct.
The tempting optimisation is to run a single gateway and point all AZs at it. That saves the hourly charge on the gateways you removed, and then adds inter-AZ data transfer on every byte from the other zones, charged in both directions on top of the NAT processing you were already paying.
At low volume this can genuinely come out ahead. At any real volume it is a loss, and it also means a single-AZ failure takes out egress for your entire VPC. Work out the arithmetic for your own gigabyte figure before taking it - this is the one place on this page where the intuitive saving is frequently negative. The data transfer cost breakdown covers the inter-AZ rates that apply here.
NAT Gateway, NAT instance, endpoints, or nothing
| Option | Cost shape | HA | Ceiling | Pick it when |
|---|---|---|---|---|
| NAT Gateway | Hourly per AZ + per GB | Managed within an AZ | Scales automatically to 100 Gbps | Default. Production, any meaningful volume. |
| NAT instance | Instance hours only - no per-GB | You build it | Instance network limit | High steady volume where per-GB dominates and you will genuinely own the HA and patching. |
| VPC Gateway Endpoint | Free | Managed | S3 and DynamoDB only | Always. Not an alternative to NAT - a way to take traffic off it. |
| Interface Endpoint | Hourly per AZ + per GB | Managed | Most AWS services | High-volume traffic to one specific service; compare its per-GB rate against NAT's. |
| Egress-only IGW | Free | Managed | IPv6 only | IPv6 workloads. See below. |
| Nothing | Free | n/a | n/a | The subnet does not need outbound internet at all. Check before you assume. |
On NAT instances specifically: the crossover point is real arithmetic, not a preference. A NAT instance has no per-gigabyte charge, so at high steady throughput it can be dramatically cheaper. It is also a single point of failure you now maintain, patch, monitor and capacity-plan, and its throughput is capped by the instance type. If the saving is a few hundred dollars a month, it is not worth the operational surface. If it is five figures, it probably is.
When NAT Gateway is the wrong answer entirely
If your workloads are IPv6, you do not need NAT at all. An egress-only internet gateway provides exactly the same property - outbound connections permitted, inbound blocked - and it is free. No hourly charge, no processing charge. Teams carry a NAT Gateway bill for years on workloads that could have used an egress-only IGW from the start.
And check whether the subnet needs egress at all. A surprising number of private subnets route to a NAT Gateway because the VPC template did it, not because anything in them makes outbound connections. If the only outbound traffic is to S3 and DynamoDB, a gateway endpoint covers it and the NAT Gateway can be deleted outright - both halves of the bill, gone.
The checklist
- Split your NAT bill into hourly and processing. Optimise the larger half.
- Create VPC Gateway Endpoints for S3 and DynamoDB, and confirm they are attached to the route tables your private subnets actually use.
- Run Flow Logs and quantify what is still crossing the gateway, by destination.
- For whatever remains large and service-specific, price an Interface Endpoint against NAT's per-GB rate.
- Do not consolidate gateways across AZs without doing the inter-AZ arithmetic first.
- If you are IPv6, replace NAT with an egress-only internet gateway.
- Check whether any of those subnets need outbound internet at all.
Steps 1 and 2 are free of risk and usually account for most of the recoverable amount. Put your numbers into the calculator to size it before you touch anything.
This is one node in a wider picture - see AWS cost optimization: where to look first for the order to work in, and the multi-region fintech platform write-up for a case where transfer topology drove the architecture.
If you would rather have this found for you: AWS cost optimization consulting.
Sources
- Amazon VPC pricing - NAT Gateway hourly and processing rates
- NAT gateways - behaviour and bandwidth scaling
- Gateway endpoints for S3 and DynamoDB
- Egress-only internet gateways for IPv6
- VPC Flow Logs and AWS-managed prefix lists
Tags:
Need help with this?
I offer hands-on consulting on exactly this — aws cost optimization consulting .