NAT Gateways passing no traffic
What does ZopNight detect here?
A NAT Gateway costs roughly $32 a month before a single byte crosses it. ZopNight checks four byte-counter metrics plus ActiveConnectionCount over 30 days, and reports the full cost as recoverable when all of them are flat. An unused gateway has no partial value.
Signal and threshold
| Field | Value |
|---|---|
| Rule IDs | RC-011 |
| Category | idle |
| Severity | medium |
| Metric | none — pure configuration read |
| Source | idle_nat.go |
Where it applies
The hourly charge is the point
NAT Gateway pricing has two parts: about $0.045 per hour just to exist, plus a per-GB data processing charge on top. The hourly part is roughly $32 a month and accrues whether or not anything routes through it. That is what makes an unused gateway worth finding: a fixed cost with zero utilisation, not a variable one that scales down on its own.
Why five metrics
Traffic can flow in four directions and the rule checks all of them, using the byte counters a NAT Gateway publishes to CloudWatch: BytesInFromSource,
BytesOutToDestination, BytesInFromDestination and BytesOutToSource. A gateway serving a
one-way workload would look idle on two of those and busy on the others.
ActiveConnectionCount is the fifth axis, and it catches a gateway holding open connections
that are transferring almost nothing. Such a gateway is present, but not moving bytes.
All five flat across 30 days is the bar.
Where these come from
Almost always a multi-AZ VPC built from a template. The pattern puts one NAT Gateway per availability zone for resilience, which is correct for production and expensive in a development VPC where nothing routes through two of the three.
The other common source is a private subnet that was given a NAT route for an outbound dependency that later moved to a VPC endpoint. The endpoint is cheaper and the gateway stays.
Reading BytesOutToDestination for the gateway
aws cloudwatch get-metric-statistics \ --namespace AWS/NATGateway --metric-name BytesOutToDestination \ --dimensions Name=NatGatewayId,Value=nat-0123456789abcdef0 \ --start-time "$(date -u -v-30d +%Y-%m-%dT%H:%M:%SZ)" \ --end-time "$(date -u +%Y-%m-%dT%H:%M:%SZ)" \ --period 86400 --statistics SumBefore deleting
Check the route tables that point at it. Deleting a NAT Gateway with a live route leaves a blackhole route behind, and instances in that subnet lose outbound access with no obvious cause. Remove the route first, confirm nothing breaks, then delete the gateway and release its Elastic IP, which otherwise keeps billing on its own.