What a NAT Gateway actually costs, and what regional mode changed (2026)

Akal Cloud 4 min read

Quick answer

A NAT Gateway bills $0.045 per hour plus $0.045 per GB processed in us-east-1, so an idle one costs about $32.85 a month, and AWS data transfer is charged on top of processing rather than instead of it. A standard gateway is zonal, so one serving three availability zones sends most traffic across a zone boundary. Since November 2025 a regional availability mode expands across zones automatically to maintain zonal affinity.

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):

MeterRateApplies 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.

ZonalRegional
ScopeOne Availability ZoneExpands and contracts across zones with your workloads
Public subnetRequired to host itNot required
Route tablesOne route per zone, edited as you expandOne NAT ID, same route entry across zones
IP addressesUp to 8Up to 32 per Availability Zone
Private NATSupportedNot 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.

See this on your own bill

Akal Cloud connects in about two minutes and shows the same numbers against your real AWS accounts.

Get started on AWS Marketplace

Related reading