AWS bill line item: NatGateway-Bytes
NatGateway-Bytes: why the NAT gateway line keeps growing
A NAT gateway has two lines on the bill: NatGateway-Hours for every hour it exists, and NatGateway-Bytes for every gigabyte it processes, wherever the traffic comes from or goes to [vpc-pricing]. The per-GB line is the one that grows with traffic, and it is easy to miss because it sits inside EC2-Other in Cost Explorer [aws-cfm-ec2-other].
What NatGateway-Bytes means
It counts the gigabytes of data that passed through your NAT gateways. AWS charges "for each gigabyte processed through the NAT gateway regardless of the traffic's source or destination" [vpc-pricing]. So traffic to other AWS services in the same region is billed the same as traffic to the internet.
In US East (N. Virginia) the current price list shows $0.045 per GB processed and $0.045 per NAT gateway hour [price-list-ec2]. Other regions differ; the VPC pricing page has them [vpc-pricing]. The data processing charge comes on top of normal data transfer: "You also incur standard AWS data transfer charges for all data transferred via the NAT gateway" [vpc-pricing].
At those prices, one gateway that exists for a 30-day month costs $32.40 in hours before it processes anything, and each 100 GB through it adds $4.50.
The usage types belong to the Amazon EC2 price list. In US East (N. Virginia) they have no region prefix [price-list-ec2]; elsewhere they carry one, for example USE2-NatGateway-Bytes in US East (Ohio) [region-codes].
How to find it in Cost Explorer or your Cost and Usage Report
Cost Explorer. NAT gateway charges are part of the EC2-Other service, along with EBS volumes and snapshots, Elastic IP addresses and data transfer [aws-cfm-ec2-other]. Filter Service to EC2-Other and group by Usage type; the NAT lines end in NatGateway-Bytes and NatGateway-Hours.
Cost and Usage Report (CUR). Group by the gateway to see which one carries the bytes:
SELECT line_item_resource_id,
line_item_usage_type,
SUM(line_item_usage_amount) AS gb_or_hours,
SUM(line_item_unblended_cost) AS cost
FROM cur
WHERE line_item_usage_type LIKE '%NatGateway-%'
GROUP BY 1, 2
ORDER BY cost DESC;
With resource IDs in the report, line_item_resource_id names the gateway. Your table and column names depend on how the export was set up.
CloudWatch. To see when the bytes happen, use the gateway's metrics in the AWS/NATGateway namespace: BytesOutToDestination and BytesInFromSource for traffic leaving through it, BytesInFromDestination and BytesOutToSource for traffic coming back [nat-metrics]. A step change in these lines up with a deploy or a new job far better than a monthly bill does.
Typical causes of a growing line
- Private subnets reaching Amazon S3 or DynamoDB through the NAT gateway. Without a gateway endpoint, that traffic is routed through the NAT device [gateway-endpoints], so every object read or written is processed and billed per GB.
- Pulling container images, packages or models at startup. Each new task or instance downloads the same artifacts again; scaling out multiplies the bytes.
- Chatty calls to AWS APIs or third-party services from private subnets: log shipping, metrics agents, polling loops, retries.
- Cross-AZ routing. Resources in one Availability Zone using a NAT gateway in another add cross-AZ data transfer on top of the processing charge. AWS recommends keeping resources in the same zone as the gateway, or one gateway per zone [nat-pricing-docs].
- Gateways nobody uses. Each one still bills hours. A test VPC left running is a steady NatGateway-Hours line with almost no bytes.
Price history
CostPulse's price history (every version of the AWS Price List since 2015) has no change to an existing On-Demand price for NatGateway-Bytes and NatGateway-Hours in Amazon Elastic Compute Cloud. It records changes to prices that already existed; a charge that arrives as a new price list entry, or a price AWS sets on a new SKU, is not a change in this sense.
So if this line went up, the cause is the bytes, not the price: the per-GB rate in the current US East (N. Virginia) price list is $0.045 [price-list-ec2], and no change to an existing NatGateway price appears anywhere in the history.
What to do about it
- Add gateway endpoints for Amazon S3 and DynamoDB to the route tables of private subnets. There is no additional charge for gateway endpoints [gateway-endpoints], and the traffic stops passing through the NAT gateway.
- Consider interface endpoints for other AWS services that carry most of your NAT traffic. They have their own hourly and per-GB prices, so compare them on the AWS PrivateLink pricing page first [nat-pricing-docs].
- Keep traffic in its zone: one NAT gateway per Availability Zone with resources, and route tables that point each subnet at the gateway in its own zone [nat-pricing-docs].
- Cache what you download: pull images from a registry in the same region, keep package mirrors close, and avoid re-downloading the same files on every start.
- Delete idle gateways found in the CUR query above with hours but almost no bytes.
- Alert on the line, not the month. A daily alert on EC2-Other or on NatGateway-Bytes catches a new data path within days. The NAT gateway article on the CostPulse blog walks through the routing in more detail.
Sources
- Amazon VPC pricing (NAT gateway) (checked 2026-10-13)
- AWS Price List API: Amazon EC2, NatGateway-Hours and NatGateway-Bytes, US East (N. Virginia), version 20261012193925 (published 2026-10-12)
- AWS Cloud Financial Management blog: Tips and tricks for exploring your data in AWS Cost Explorer, part 2 (September 18, 2019)
- Amazon VPC User Guide: Pricing for NAT gateways
- AWS PrivateLink guide: Gateway endpoints
- Amazon VPC User Guide: NAT gateway metrics and dimensions
- AWS Region billing codes
Page last reviewed 2026-10-13. Prices quoted as "current" are from the AWS Price List version named next to them and can change; the AWS pricing pages are authoritative.