~12 min
A NAT gateway bills two ways at once: an hourly charge for every Availability Zone it's provisioned in, plus a per-GB charge for every gigabyte it processes, in both directions — and that data-processing charge applies on top of any standard data transfer charge for traffic leaving to the internet. Traffic to AWS services that support VPC endpoints — Amazon S3 and DynamoDB via a gateway endpoint, dozens of other services via an interface endpoint — can bypass the NAT gateway entirely. A gateway endpoint costs nothing at all: no hourly charge, no per-GB charge, just a route added to the subnet's route table. An interface endpoint isn't free (it has its own small hourly and per-GB charge), but for high-volume traffic to a service like Secrets Manager or CloudWatch Logs, it's usually still cheaper than paying the NAT gateway's processing charge on the same traffic. For a private subnet whose NAT traffic is mostly bound for a small number of AWS services, adding the matching endpoints is close to a free reduction in NAT gateway cost.
bash
aws ec2 create-vpc-endpoint \
--vpc-id vpc-0123456789abcdef0 \
--service-name com.amazonaws.us-east-1.s3 \
--route-table-ids rtb-0123456789abcdef0 \
--vpc-endpoint-type GatewayHow many NAT gateways to run is its own tradeoff. A single shared NAT gateway in one AZ costs the least in baseline hourly charges, but every private subnet in a different AZ routing through it pays cross-AZ data transfer charges on top — acceptable for a development environment with light, non-critical traffic, and also a single point of failure if that AZ has a problem. One NAT gateway per AZ costs more in baseline hourly charges (one gateway-hour per AZ instead of one), but keeps every subnet's NAT traffic inside its own AZ, avoiding the cross-AZ charge and the single point of failure — the standard choice for a production workload with real traffic volume.
Which one is actually cheaper depends on the numbers: above roughly a few terabytes a month of cross-AZ NAT traffic, the extra cross-AZ charges on a shared NAT gateway can exceed the cost of simply running one gateway per AZ, making the "more expensive-looking" option the cheaper one in practice.
Connecting several VPCs together has the same shape of tradeoff. VPC peering has no hourly charge for the connection itself — you pay only standard data transfer rates for the traffic that crosses it — but it isn't transitive: if VPC A peers with B and B peers with C, A still can't reach C without a direct peering connection of its own. Connecting n VPCs this way needs up to n(n-1)/2 peering connections, which gets unwieldy fast. AWS Transit Gateway costs an hourly charge per attachment plus a per-GB charge, but every attached VPC can reach every other one through a single hub, with no mesh of individual connections to manage. For a handful of VPCs, peering is usually cheaper and simpler; past that, Transit Gateway's per-attachment cost is often lower than the operational and cross-AZ cost of maintaining a growing peering mesh.
28 — n(n-1)/2 with n=8 is 8×7/2=28. This is exactly the kind of growth that makes Transit Gateway's single-hub model worth its per-attachment cost once a VPC count gets this large.