Skip to content

NAT Gateway vs VPC Endpoints: Follow the Route, Then Calculate the Bill

By

In this article

You have an application in a private subnet, and most of its outbound traffic goes to S3. Its default route points to a NAT gateway. An S3 gateway endpoint can remove that traffic from NAT even though DNS still returns public S3 addresses. Add an interface endpoint for every AWS API, though, and your bill may go up.

What matters here? Where do these requests go, which path do they take, and what fees does that path generate?

Follow the request

Let's say we have an IPv4 VPC in us-east-1 (a fan favourite default for examples) with application subnets across three AZs, each with a zonal NAT gateway and Elastic IP. The application also calls external APIs, so all three NAT gateways remain. Assume the following monthly traffic in GB, counting request and response bytes once:

Destination GB
S3 12,000
DynamoDB 1,200
CloudWatch Logs 1,500
Secrets Manager 10
STS 20
External APIs 300
Total 15,030

Initially, S3 requests follow the subnet's default route through NAT. S3 traffic stays on the AWS network, but NAT still processes the bytes. Adding an S3 gateway endpoint inserts a more specific regional service prefix-list route into each associated route table. That route wins over 0.0.0.0/0. Remember: S3's public DNS answer does not change. DynamoDB works the same way.

Associate both gateway endpoints with all three application route tables; a missing association leaves that subnet using NAT. Cross-Region service calls also miss the regional prefix.

CloudWatch Logs behaves differently. An interface endpoint creates private ENIs in selected AZs. With private DNS enabled, the usual Logs hostname resolves to these addresses, and the VPC's local route reaches an endpoint ENI. Its security group must allow HTTPS traffic from the application.

Creating an endpoint alone is not enough if the client uses another DNS path. Regional DNS may select an ENI in another AZ, so three ENIs do not guarantee same-AZ connections.

For an actual workload, estimate service bytes from application ENI Flow Logs and reconcile them with billing. DNS queries can identify destinations, but not byte volume.

Calculate the incremental bill

AWS prices change. When pricing was checked, the public us-east-1 rates were $0.045/hour and $0.045/GB for a zonal NAT gateway, plus $0.005/hour per public IPv4 address. Gateway endpoints had no additional charge. An interface endpoint cost $0.01/hour per selected AZ plus $0.01/GB at this workload's processing tier. Sources: VPC pricing and PrivateLink pricing. This 730-hour model excludes service requests, storage, compute, tax, discounts, and external data-transfer charges.

Three NAT gateways and addresses cost 3 × 730 × ($0.045 + $0.005) = $109.50 before processing. Processing all 15,030 GB adds $676.35, for a $785.85 subtotal.

S3 and DynamoDB gateway endpoints divert 13,200 GB, saving 13,200 × $0.045 = $594. The subtotal falls to $191.85. NAT's $109.50 fixed cost remains because the external APIs still need it.

For an interface endpoint in three AZs, the fixed charge is 3 × 730 × $0.01 = $21.90. Each GB costs $0.01 instead of $0.045 in NAT processing, so it breaks even at about 21.90 / (0.045 - 0.01) = 626 GB/month. This assumes the NAT gateways remain and each path processes the same bytes.

Logs exceeds that threshold: its endpoint costs $36.90 instead of $67.50 in NAT processing. Gateway endpoints plus Logs bring the combined networking subtotal to $161.25. Secrets Manager's 10 GB and STS's 20 GB each save less than $1 in NAT processing, but each three-AZ endpoint adds at least $21.90 fixed. Adding both raises the combined subtotal to $204.00. I'd add them for a private-path requirement, not for savings in this workload.

Don't mix up authorization

An endpoint policy limits requests through that endpoint; it does not replace IAM or resource policies. Valid credentials might still reach a public service endpoint through the remaining NAT. If a bucket must accept requests only through an approved endpoint, an S3 bucket-policy condition on aws:SourceVpce can enforce that boundary. Test console, administrator, and recovery access before applying a deny.

Conclusion

For this workload, I'd associate S3 and DynamoDB gateway endpoints with all application route tables, add Logs interface endpoints in three AZs, and keep NAT for external APIs and low-volume AWS calls. After rollout, I'd verify the routes, DNS destinations, service bytes, and bill. Adding a gateway endpoint can interrupt existing S3 connections, so I'd make the change in a controlled window. I'd add another endpoint only when a measured cost or policy need justifies it.