NAT cost is the cost of a network path
An AWS NAT gateway bill is not settled by one hourly rate. The actual charge accumulates from the hours the gateway was on, the request and response data that crossed the NAT, the data transfer legs on either side, and adjacent constructs such as public IPv4 and endpoints.
So the first question in a NAT cost analysis is not "how many NAT gateways are there?" but which workload talks from which availability zone to which destination and how much. S3 and DynamoDB traffic, specific AWS APIs, the general IPv4 internet, and IPv6 destinations each lead to a different path and a different alternative.
A regional NAT gateway does not change this. It simplifies multi-AZ operation with a single ID and automatic zone expansion. Every active or configured zone still carries an hourly charge, and processed data, data transfer, and public IPv4 costs all remain.[2]
Traffic leaving the same private subnet splits by destination. S3 and DynamoDB come off the NAT path through a gateway endpoint. Services behind PrivateLink use an interface endpoint, which adds a fresh hourly charge per zone. IPv6 destinations go through an egress-only internet gateway, and reaching IPv4-only destinations needs NAT64.[3]
The NAT path cost formula
NAT cost decomposes safely into five terms. Total NAT path cost is defined by the calculation entries below. The terms mean the following.
Running one zonal NAT for a full month produces the hourly cost of one gateway. If a regional NAT supported three zones over the same period, the resource ID is single but the AZ-hours are tripled. In automatic mode the zones actually expanded set the hourly cost; in manual mode the configured zones do. Partial hours round up to one hour.[1][2]
Do not put 730 hours into the month. That figure is convenient for an annual average and is not a billing period. A 30-day month is 720 hours, a 31-day month is 744, a non-leap February is 672, and a resource created or deleted mid-month takes its actual provisioned hours. A regional NAT splits those hours again by zone. If one zone appeared mid-month, the same monthly hours cannot be applied to every zone.
NAT processing does not mean outbound alone. The gateway processes both the request leaving for the destination and the response coming back. One GB of request with three GB of response estimates to four GB. When estimating from CloudWatch, use only one pair: BytesInFromSource with BytesInFromDestination, or BytesOutToDestination with BytesOutToSource. Adding all four counts the same packet twice, once entering and once leaving the NAT.[6]
Final verification favours the NAT data processed usage in the CUR or Cost Explorer over a CloudWatch estimate. Regional NAT metrics are read with the NatGatewayId and AvailabilityZone dimensions together.[5]
Do not mix GB and GiB inside one calculation. AWS price sheets and invoices generally use GB while CloudWatch returns raw bytes. In the worksheet, either take the billed GB from the CUR or Cost Explorer directly, or, when working from raw bytes, state which rule applies: GB as 10^9 bytes or GiB as 2^30 bytes. Never switch rules midway, and reconcile against the invoice line item at the end. Feeding an already converted value into the price sheet's GB column and dividing by 1,024 again is the same mistake.
- H_nat,z
- Gateway hours per zonal NAT, or supported hours per availability zone for a regional NAT.
- B_nat,billed
- Request and response data that actually passed through the NAT and was billed.
- B_leg,billed
- Billed data on each leg, such as cross-AZ, internet egress, or inter-region transfer.
- H_ip
- Hours of the public IPv4 addresses actually attached to the NAT.
- C_adjacent
- Cost added by an alternative construct such as an interface endpoint or a NAT instance.
- Total NAT path cost
- C_NAT_PATH = Σz ceil(H_nat,z) × P_nat_hour + B_nat,billed × P_nat_process + Σleg (B_leg,billed × P_transfer,leg) + Σip (H_ip × P_public_ipv4) + C_adjacent
From cost drivers to ongoing control — Break down spending by workload and resource, assess each change and carry budget guardrails into operations.
What the Seoul region adds
On the Seoul price sheet a NAT gateway is $0.059 per hour and processed data is $0.059 per GB. Three further items attach depending on the real path.[1]
The first is the cost of crossing an AZ boundary. If the private workload sits in AZ-A and the zonal NAT in AZ-B, requests and responses between them cross that boundary. The AWS VPC pricing page states that data transfer cost applies when EC2 and the NAT sit in different zones. Same-region EC2-family transfer between zones generally records $0.01 per GB on both the sending and the receiving side. Which party is billed and which exemptions apply still varies with intermediate resources such as load balancers, PrivateLink, or VPC peering. Rather than putting traffic times two into the formula, match the APN2-DataTransfer-Regional-Bytes rows in the CUR against the real boundaries.[1][5][7]
The second is internet data transfer out. The NAT processing charge does not include internet transfer. Sending data to an external API or an internet destination attaches EC2 data transfer out at its own destination and tier rates. Conversely, sending a file to S3 in the same region carries no EC2-to-S3 transfer cost, yet the NAT processing charge remains if the traffic crossed the NAT. That is why destination types are separated first.[1]
The third is public IPv4 hours. A public NAT gateway carries a public IPv4 address for internet communication, and public IPv4 is charged per address per hour. If a regional NAT uses several addresses according to throughput or connection count, the actual IP-hours are checked too. Rather than assuming the address count equals the NAT count, aggregate from Public IP Insights or the APN2-PublicIPv4:InUseAddress billing rows.[5]
What the regional NAT gateway changed
A conventional multi-AZ zonal NAT layout generally required five things: a public subnet in each zone, a NAT gateway per zone, a local NAT route per private subnet, a route from the NAT subnet to the internet gateway, and a NAT and route table edit every time a zone was added.
A regional NAT provides a single NAT ID at the VPC level. It needs no NAT placed in a public subnet, and in automatic mode it detects the zones where workload network interfaces exist and expands or contracts accordingly. Within each zone it prefers that zone's regional NAT point to preserve zonal affinity.[2]
Seven conditions still need checking first. Per-AZ billing remains. Private NAT is unsupported, so a transit gateway, VPN, or on-premises connection needing private address translation calls for a zonal NAT. Expansion into a new zone can take up to 60 minutes, during which another zone handles the traffic, so the real cross-AZ path is verified. Constrained zones are unsupported. In manual mode the operator manages zone and IP expansion. Cutting over from an existing NAT resets connections, so a maintenance window and any external allowlist IP change are required. The public IPv4 count can grow: a regional NAT supports up to 32 addresses per zone, so connection scale and IP-hours are read together.
A regional NAT is mainly an option for reducing the complexity and misrouting risk of multi-AZ NAT operation. The cost judgment is recomputed against the zonal layout using the same zone count, throughput, public IPs, and transfer paths.[2]
Comparing the alternatives
Eight options sit on the same axes: fixed cost, variable cost, availability, operating burden, the traffic they serve, and the condition to watch.
A gateway endpoint is limited to S3 and DynamoDB but carries no hourly or processing charge of its own. An interface endpoint creates an endpoint ENI per zone per service and charges for processing regardless of direction. Two or more zones are recommended in production, so a higher availability requirement raises the hourly fixed cost.[3]
An egress-only internet gateway is a stateful gateway that permits only IPv6 outbound connections and has no hourly charge of its own. The external destination still has to support IPv6, and internet data transfer is separate. IPv4-only destinations need DNS64 and NAT64, and that path attracts NAT gateway charges again.[1][8]
AWS recommends the NAT gateway by default on grounds of management burden, availability, and bandwidth. Choosing a NAT instance means building it on current Amazon Linux rather than an old NAT AMI, and taking on redundancy, patching, monitoring, and failover yourself.[4]
Option | Fixed cost | Variable cost | Availability | Operating burden | Traffic it serves | Condition to watch |
|---|---|---|---|---|---|---|
| Zonal NAT gateway | Gateway times hours in use | NAT processing, data transfer, IPv4 | Managed redundancy within an AZ. Multi-AZ needs one per zone | Low to medium | General IPv4 internet, public and private NAT | Sharing another zone's NAT widens both cost and blast radius |
| Regional NAT gateway | Active and configured AZs times hours in use | NAT processing, data transfer, actual IPv4 | AZ expansion and zonal affinity in automatic mode | Low | General public IPv4 internet | No private NAT, expansion delay, connections reset on cutover |
| Gateway endpoint | No additional endpoint cost | No endpoint processing cost | Managed by AWS | Low | Same-region S3 and DynamoDB | Applies to no other service and is constrained beyond the VPC |
| Interface endpoint / PrivateLink | Services times endpoint AZs times hours | Endpoint processing and any required transfer | Improves with a multi-AZ layout | Medium | Supported AWS services, SaaS, endpoint services | Many services with little traffic makes the fixed cost dominate |
| Native IPv6 with egress-only IGW | No gateway cost | Internet data transfer and similar | Managed by AWS | Medium | Destinations that support IPv6 | Application, DNS, firewall, and external dependencies must support IPv6 |
| DNS64 with NAT64 | NAT gateway hours and IPv4 | NAT processing and transfer | Follows the NAT layout | Medium | IPv6-only source to IPv4-only destination | NAT cost remains and the DNS64 and 64:ff9b::/96 path is required |
| NAT instance | EC2, EBS, IPv4, HA instances | Transfer volume and instance usage | Redundancy and failover you design yourself | High | General NAT plus custom network functions | Patching, capacity, failure, port exhaustion, and recovery are yours |
| Reducing the traffic itself | Build cost of caches, mirrors, endpoints | Reduced traffic plus the new construct's cost | Depends on the design | Medium | Repeated downloads, polling, retries, telemetry, artifacts | Check whether the traffic was removed or merely moved to another bill |
The endpoint break-even is not set by data volume alone
Monthly interface endpoint cost is roughly C_INTERFACE = N_services × Σaz ceil(H_endpoint,az) × P_endpoint_hour + B_endpoint × P_endpoint_process + C_transfer. The simple break-even for moving from NAT to an interface endpoint is the endpoint's fixed hourly cost divided by the avoided NAT processing rate plus the avoided transfer rate minus the endpoint processing rate.
If that denominator is zero or below, more data never makes the endpoint cheaper on cost alone. Six further factors enter the calculation: how many services need endpoints; how many endpoint zones production requires; which cross-AZ or internet legs the endpoint avoids; the value of private DNS and the security policy; whether the NAT gateway stays anyway for other traffic; and the minimum NAT fixed cost that survives the move.
Where the NAT cannot be removed entirely, what an endpoint reduces is usually a portion of NAT processing. In that case the endpoint's hourly fixed cost is set beside the variable cost it removes.
Operations connected from observation to improvement — Respond using service indicators and alerts, then connect change records and incident reviews to improvements.
Decision matrix
Which option to open first depends on the shape of the traffic today. The nine rows below pair a traffic shape with the alternative to review and the items to confirm next.
Current traffic | Option to review first | What to check next | Why |
|---|---|---|---|
| Same-region S3 and DynamoDB dominate | Gateway endpoint | Route tables, endpoint policy, cutting over existing connections | The endpoint itself has no hourly or processing charge and splits the NAT path off |
| Steady heavy traffic to a few AWS APIs or SaaS | Interface endpoint | Service support, number of AZs, private DNS, break-even | You gain a private path and access control at a fixed cost per service and zone |
| Many unspecified IPv4 internet destinations | Zonal or regional NAT | Number of AZs, need for private NAT, allowlisted IPs, operating model | Endpoints cannot replace the general internet |
| Multi-AZ public NAT changes often | Regional NAT | Automatic or manual mode, supported AZs, expansion delay, IP policy | Simplifies NAT and route table operation while keeping per-AZ affinity |
| Private NAT needed on on-premises or TGW paths | Zonal private NAT | Routing, AZ redundancy, address overlap | Regional NAT does not support private NAT |
| Destinations and application both support IPv6 | Native IPv6 with egress-only IGW | DNS, security groups, NACLs, external APIs, observability tools | The NAT44 processing path is no longer needed |
| IPv6-only source calling IPv4-only APIs | DNS64 with NAT64 | DNS64, 64:ff9b::/96, public NAT, testing | The IPv6-only workload survives, but NAT cost remains |
| Low or intermittent traffic with custom needs | NAT instance as candidate | EC2 sizing, HA, failover, patching, source/destination check | You trade managed cost for operational duty and capacity risk |
| Artifacts, packages, logs, and retries dominate NAT usage | Reduce the traffic itself | Cache hit rate, retries, transfer frequency, compression, mirrors | Remove unnecessary bytes before swapping network devices |
NAT cost worksheet
The worksheet has three blocks. Block A holds the inputs common to every calculation. Block B is the per-destination traffic rows, and block C is the formula per cost component.
Each traffic row in block B records one path. Its columns are source and AZ, destination, IP family, request, response, current path, NAT type and AZ, cross-AZ boundary, endpoint AZ, and internet egress.
Three values are computed per row. NAT processing is the sum of request and response that crossed the NAT. Cross-AZ billed volume is the sum of bytes on each boundary that is actually billed. Internet egress is the real response and upload leaving for the internet minus any applicable free tier or exemption.
Data that left through an endpoint or a cache is subtracted from NAT processing. Conversely, internet egress and NAT processing being the same data is no reason to count only one of them. They are different meters.
- Valuation date
- The date the prices were verified. Price sheets change, so this is re-checked with every calculation.
- Region
- The region every resource and price belongs to. Seoul is ap-northeast-2.
- Currency
- The display currency before any exchange rate is applied.
- Tax
- Recorded as included or excluded so a quote and an actual invoice can be compared.
- Analysis period
- The start and end dates, and whether the window is a calendar month or an arbitrary range.
- Unit
- One fixed rule among CUR GB, GB, and GiB.
- Commitments and credits
- An amount or an explicit exclusion, so service cost and final invoice stay separate.
Cost component | Formula |
|---|---|
| Zonal NAT hours | Sum of rounded hours per gateway times $0.059 |
| Regional NAT hours | Sum of rounded support hours per AZ times $0.059 |
| NAT processing | CUR NAT processed GB times $0.059 |
| Cross-AZ | Sum of billed leg GB times the applicable data transfer rate |
| Internet egress | The GB in question times the Seoul destination and tier rate |
| Public IPv4 | Actual IP hours times $0.005 |
| Gateway endpoint | $0 endpoint hour plus $0 endpoint processing |
| Interface endpoint hours | Number of services times endpoint hours per AZ times $0.013 |
| Interface endpoint processing | Actual processed GB times the applicable tier |
| NAT instance compute | Runtime per instance times the Seoul on-demand rate |
| NAT instance extras | EBS plus IPv4 plus transfer plus monitoring plus HA replica |
| Operating cost | Internal cost of patching, incident response, failover tests, and on-call |
The metric checklist to complete before the analysis
Metrics are gathered in five areas: billing, topology, traffic, reliability, and change plan.
Cost Explorer and the CUR expose NAT hours and processing, inter-AZ data transfer, internet egress, VPC endpoint hours and processing, and public IPv4 as distinct usage types. Reading a single "VPC cost" total makes it hard to tell which path caused it.[5]
Area | Item to gather | What it answers |
|---|---|---|
| Billing | NAT gateway running hours, data processed | Separates hourly cost from processing cost |
| Billing | APN2-DataTransfer-Regional-Bytes | Confirms cross-AZ cost |
| Billing | Internet data transfer out | Separates NAT processing from internet transfer |
| Billing | APN2-VpcEndpoint-Hours, APN2-VpcEndpoint-Bytes | Endpoint fixed and variable cost |
| Billing | APN2-PublicIPv4:InUseAddress | IPv4 cost of NAT and other resources |
| Billing | NAT instance EC2, EBS, data transfer | Total cost of a self-managed NAT |
| Topology | NAT ID, zonal or regional, automatic or manual | Confirms the billing unit and operating model |
| Topology | Subnet, route table, and AZ mapping | Detects cross-AZ hairpins |
| Topology | Regional NAT supported AZs and actual IPs | Confirms AZ-hours and IP-hours |
| Topology | List of gateway and interface endpoints | Destinations that can be split off the NAT |
| Topology | Private DNS and endpoint policy | Confirms that traffic actually reaches the endpoint |
| Topology | IPv6 CIDR, ::/0, 64:ff9b::/96 | Confirms the native IPv6 and NAT64 paths |
| Traffic | BytesInFromSource, BytesInFromDestination | Estimates processing including both request and response |
| Traffic | ActiveConnectionCount | Confirms connection scale and port usage |
| Traffic | ErrorPortAllocation | Whether ports are running out |
| Traffic | Source, destination, and bytes in VPC flow logs | Classifies destinations and the workloads behind them |
| Traffic | Share of retries, polling, artifacts, telemetry | Identifies removable traffic |
| Reliability | Egress path during an AZ failure | Marks the segments where availability outranks cost |
| Reliability | Tolerance for regional NAT expansion time | Temporary cross-AZ effects when a new AZ appears |
| Reliability | External allowlisted IP requirements | Whether NAT change or cutover is possible |
| Reliability | NAT instance failover and patch history | Sizes operating cost and failure risk |
| Change plan | Route change order and rollback | Safety of an endpoint or regional NAT cutover |
| Change plan | Acceptable window for connection resets | The maintenance window for a NAT cutover |
| Change plan | CUR over identical periods before and after | Verifies savings and detects cost that merely moved |
In what order should things change?
The first step is not deleting the NAT but building a per-destination traffic inventory. Split S3 and DynamoDB traffic out as gateway endpoint candidates, and split off the supported services that repeatedly take a large share as interface endpoint candidates. Divide external internet traffic into APIs, artifacts, telemetry, updates, and user data.
Next, confirm the AZ boundary between source and NAT, and separate destinations reachable directly over IPv6 from those needing NAT64. Compute the hourly fixed cost and the operating duty each alternative creates, then compare before and after using the CUR over identical periods.
That sequence leads to a sharper question than "should the NAT be replaced by another device": which traffic comes off the NAT, which traffic stays on the managed NAT, and which traffic should never have existed.



