What a NAT Gateway really costs — and how to schedule it
The NAT Gateway is the most expensive thing in most non-production VPCs that nobody looks at. It has no stop button, its charge is decoupled from traffic, and high-availability guidance quietly multiplies it per Availability Zone. Here is the arithmetic and the only mechanism that actually reduces it.
The two charges
A NAT Gateway bills on two axes in us-east-1:
- Hourly charge:
$0.045per gateway-hour, billed 24/7 the moment the gateway exists — independent of whether a single byte flows through it. - Data processing:
$0.045per GB of data processed through the gateway.
Traffic that crosses an Availability Zone boundary also incurs standard inter-AZ data transfer
(on the order of $0.01/GB per direction — TODO(verify)),
but for a dormant environment the number that matters is the first one: the hourly charge you pay
for nothing.
The hourly charge is fixed. An environment that is completely idle overnight —
zero data processed — still pays the full $0.045/hour. Utilization-based instincts
do not apply; there is no scale-to-zero.
What a dormant multi-AZ setup burns
AWS's own high-availability guidance is one NAT Gateway per Availability Zone, so that a zone failure does not take out egress for the others. That is sound architecture — and it means the fixed hourly charge is paid per zone. For an environment that is only genuinely used ~45 hours of the 168-hour week, here is the hourly-charge cost of leaving the gateways up 24/7 versus scheduling them down outside working hours (us-east-1, hourly charge only):
| NAT Gateways | Always-on / month | ~45 hrs/week scheduled | Monthly saving |
|---|---|---|---|
| 1 (single-AZ) | $32.40 | $8.68 | $23.72 |
| 2 (two-AZ) | $64.80 | $17.36 | $47.44 |
| 3 (three-AZ) | $97.20 | $26.03 | $71.17 |
The math is $0.045 × 720 hours for always-on, and $0.045 × ~193 hours
(45 hours/week over a 30-day month) for the scheduled case, per gateway. Data processing is
on top and is genuinely usage-based, so it largely disappears on its own when the environment is
idle — the hourly charge is the part scheduling recovers.
Why you can't just stop it
Unlike EC2 and RDS, a NAT Gateway exposes no stop/start. The API surface is
create-nat-gateway and delete-nat-gateway and nothing in between. To stop
paying for an idle gateway you must delete it, and to bring the environment back you must create a
new one — a new gateway with a new ID — then repair the route tables that pointed at the old one.
One detail makes this tractable: the Elastic IP. A NAT Gateway's public address is an EIP you allocate. If you keep the EIP allocation when you delete the gateway, you can re-associate the same address on the replacement, so anything downstream that allowlists your egress IP keeps working across the cycle.
Since 1 February 2024, AWS charges $0.005/hour for every public IPv4 address,
including in-use and idle Elastic IPs — about $3.60/month per address. Keeping
the EIP allocated between cycles costs this whether the gateway is up or not, and it is far
cheaper than the $32.40/month gateway it preserves. TODO(verify current public IPv4 rate)
Scheduling a NAT Gateway: the delete/recreate cycle
The off-window action deletes the gateway; the on-window action recreates it and re-points the route. The shape of it, in the AWS CLI:
# --- OFF window: tear down, keep the EIP allocation ---
aws ec2 delete-nat-gateway --nat-gateway-id nat-0abc123
aws ec2 wait nat-gateway-deleted --nat-gateway-id nat-0abc123
# the route to 0.0.0.0/0 via nat-0abc123 is now blackholed; leave or remove it
# --- ON window: recreate in the same subnet, reuse the same EIP ---
NAT_ID=$(aws ec2 create-nat-gateway \
--subnet-id subnet-0public456 \
--allocation-id eipalloc-0kept789 \
--query 'NatGateway.NatGatewayId' --output text)
aws ec2 wait nat-gateway-available --nat-gateway-id "$NAT_ID"
# repoint the private route table at the new gateway id
aws ec2 replace-route \
--route-table-id rtb-0private012 \
--destination-cidr-block 0.0.0.0/0 \
--nat-gateway-id "$NAT_ID"
That is the happy path for one gateway. A safe implementation has to handle the parts that bite:
- Provisioning latency.
create-nat-gatewaytakes on the order of a couple of minutes to reachavailable. Your on-window has to fire early enough that egress is ready before the environment is in use. - Route table discovery. Every private route table that used the old gateway needs its
0.0.0.0/0route repointed. Enumerate them rather than hardcoding one. - Dropped connections. Deleting a gateway drops in-flight connections. This is fine for idle non-production; do not do it to anything with active long-lived flows.
- EIP accounting. Track the allocation ID you are preserving so recreation is deterministic and you are not leaking addresses.
This orchestration — waiters, per-route-table repointing, EIP reuse, and doing it on a timezone-aware schedule — is exactly what Uptime Scheduler runs for NAT Gateways tagged for scheduling, inside your own account.
FAQ
How much does a NAT Gateway cost per month?
About $32.40/month per gateway in us-east-1 for the hourly charge alone
($0.045 × 720), plus $0.045/GB processed. A three-AZ HA setup is
roughly $97.20/month before any data processing.
Can you stop a NAT Gateway to save money?
No — there is no stop API. The only lever is delete-and-recreate, preserving the Elastic IP and repointing the affected route tables.
Why are NAT Gateway costs so hard to notice?
The charge is fixed and traffic-independent, it hides under the generic EC2-Other
usage type in Cost Explorer, and HA designs multiply it per AZ. An idle environment shows almost
no data processing while still paying the full hourly charge on every gateway.
See how many idle gateways you're paying for
upscan is our free CLI — run
upscan --resources nat --region us-east-1 and it lists your NAT Gateways with their
traffic and monthly cost. No signup, no account. It just tells you the number.