A NAT Gateway bills on two meters at once, and the charge that usually hurts is on neither of them. As of November 2025 there is also a second kind of NAT Gateway that changes the answer, so this is worth revisiting even if you costed it out before.
What does a NAT Gateway charge for?
Per the Amazon VPC pricing page, in US East (N. Virginia):
| Meter | Rate | Applies to |
|---|---|---|
| Hourly availability | $0.045 per hour | Per gateway, whether or not it passes a single byte |
| Data processing | $0.045 per GB | Every GB through the gateway, in either direction |
The hourly charge is the one worth internalising: an idle NAT Gateway still costs about $32.85 a month at 730 hours. A forgotten gateway in a dev VPC bills the same as a busy one in production.
Processing is not the whole story either. The same pricing page states that "you also incur standard AWS data transfer charges for all data transferred via the NAT gateway", so processing sits on top of transfer rather than instead of it. Current transfer rates, including the 100 GB per month of free internet egress AWS applies across services and regions, are on the EC2 on-demand data transfer pricing page. Read them there rather than trusting a number in a blog post: rates change, and a stale figure is worse than no figure.
Why does one gateway across three AZs cost more?
A standard NAT Gateway is zonal. The NAT gateway basics documentation states that "each NAT gateway is created in a specific Availability Zone and implemented with redundancy in that zone."
So one gateway serving a three-AZ VPC means instances in the other two zones reach it across a zone boundary, and that traffic picks up cross-AZ data transfer on top of processing and egress.
Worth being precise about what AWS actually recommends here, because it is easy to misquote. The same page says: "If you have resources in multiple Availability Zones and they share one NAT gateway, and if the NAT gateway's Availability Zone is down, resources in the other Availability Zones lose internet access. To improve resiliency, create a NAT gateway in each Availability Zone, and configure your routing to ensure that resources use the NAT gateway in the same Availability Zone." The stated reason is resiliency, not cost. Keeping traffic in-zone is a consequence of that layout, and a welcome one, but AWS is not making a billing argument.
What changed in November 2025?
AWS added a regional availability mode for NAT Gateway, which makes the old "one gateway or one per zone" question largely obsolete. Per the regional NAT gateway documentation, a regional gateway "automatically expands across Availability Zones based on your workload presence", using one NAT ID and one route entry for subnets in every zone.
| Zonal | Regional | |
|---|---|---|
| Scope | One Availability Zone | Expands and contracts across zones with your workloads |
| Public subnet | Required to host it | Not required |
| Route tables | One route per zone, edited as you expand | One NAT ID, same route entry across zones |
| IP addresses | Up to 8 | Up to 32 per Availability Zone |
| Private NAT | Supported | Not supported |
The documented benefit that matters for cost is that a regional gateway expands "to maintain zonal affinity", which is the thing you were manually buying with one gateway per zone. AWS's own guidance is to "consider using Regional NAT Gateways for all use cases except those that require private connectivity."
One caveat worth knowing before you assume cross-zone traffic disappears: the same documentation notes it "may take your regional NAT Gateway up to 60 minutes to expand to a new Availability Zone after a resource is instantiated there", and until it does, "the relevant traffic from this resource is processed across zones". A zone that scales up quickly will cross zones for up to an hour.
Creating one is a single flag:
aws ec2 create-nat-gateway \
--vpc-id vpc-12345678 \
--availability-mode regional
Pricing for regional mode is not separately published; the documentation points at the same VPC pricing page. Check it against your own bill rather than assuming it matches zonal.
How do you find what yours is costing?
List every gateway, and the subnet, and therefore the zone, each one sits in:
aws ec2 describe-nat-gateways \
--filter Name=state,Values=available \
--query 'NatGateways[].[NatGatewayId,SubnetId,VpcId]' \
--output table
Then pull the spend, split by usage type, from Cost Explorer:
aws ce get-cost-and-usage \
--time-period Start=2026-07-01,End=2026-08-01 \
--granularity MONTHLY \
--metrics UnblendedCost \
--group-by Type=DIMENSION,Key=USAGE_TYPE \
--filter '{"Dimensions":{"Key":"SERVICE","Values":["Amazon Virtual Private Cloud"]}}'
Separate the hourly line from the per-GB line. If processing is large relative to hourly, you have a traffic problem. If regional data transfer is large relative to processing, you have a topology problem, and the fix is gateway placement rather than traffic reduction.
For traffic rather than cost, NAT Gateway publishes CloudWatch metrics at
one-minute granularity. The two worth watching are
BytesOutToDestination, "the number of bytes sent out through the
NAT gateway to the destination", and BytesOutToSource, "the
number of bytes sent through the NAT gateway to the clients in your VPC". The
NAT gateway metrics reference
lists all of them, and note the dimensions differ by mode: zonal gateways use
NatGatewayId alone, while regional gateways use it together with
AvailabilityZone.
Where does this show up in the CUR?
In the Cost and Usage Report these land in line_item_usage_type,
and you can attribute them per gateway through
line_item_resource_id. The
CUR 2.0 data dictionary
defines every column, which matters because usage-type strings are the only
reliable way to separate the hourly charge, the processing charge and the
transfer charge once they are all sitting under the same service name.