NAT Gateway Cost Trap: Cut Your AWS Bill With VPC Endpoints
NAT Gateway cost explained: $0.045/hr plus $0.045/GB, why S3 traffic hits it, and how free VPC gateway endpoints cut AWS network bills 50-80%. Guide.
- What: NAT Gateway cost is two charges: $0.045 per hour and $0.045 per GB processed, per gateway.
- Why it matters: S3, ECR and DynamoDB traffic from private subnets rides through NAT by default and gets billed.
- What to do: Add free S3 and DynamoDB gateway endpoints, audit flow logs, add interface endpoints only above 209 GB/month per AZ.
- Key stat: Uploading 1 GB through NAT costs $0.135 ($0.045 processing plus $0.09 egress). Through an S3 gateway endpoint it costs $0.
NAT Gateway cost on AWS is $0.045 per hour plus $0.045 per GB processed. One gateway costs $32.85 a month before traffic. Bills spike because S3, DynamoDB and ECR traffic from private subnets routes through NAT by default. Free gateway endpoints for S3 and DynamoDB remove that traffic and typically cut NAT data charges by 50 to 80 percent.
An AWS NAT Gateway is a managed network address translation service that lets resources in private subnets reach the internet and public AWS endpoints. It is billed per hour of existence and per gigabyte of data processed in both directions. A VPC gateway endpoint is a free route-table entry that sends Amazon S3 and DynamoDB traffic directly over the AWS network, bypassing the NAT Gateway entirely.
NAT Gateway cost is the line item that surprises more developers than any other on an AWS bill. I have watched it happen on three separate PHP projects. The compute spend was modest, yet networking charges were double the compute. Every time, the culprit was the same. The app lived in a private subnet and talked to S3 constantly. Every byte went through the NAT Gateway at $0.045 per GB. Nobody had added a gateway endpoint because nobody knew it existed. This guide explains how NAT Gateway pricing works in 2026 and how to prove where the traffic comes from. It also covers the one case where the popular fix, interface endpoints, makes your bill worse.
What is the NAT Gateway cost on AWS in 2026?
In us-east-1, a NAT Gateway costs $0.045 per hour and $0.045 per GB of data processed. Those figures come from the official Amazon VPC pricing page. That works out to $32.85 per month per gateway at 730 hours, before a single byte moves.
The data-processing part is where the NAT Gateway cost trap lives. AWS charges it on every gigabyte in both directions, on top of normal data transfer. Internet egress adds another $0.09 per GB for the first 10 TB. So a private-subnet worker uploading 1 GB to a third-party API pays $0.135 in total. Downloads skip the egress fee, but the $0.045 processing fee still applies.
High availability makes it worse. AWS advises one NAT Gateway per Availability Zone, so a three-AZ VPC starts at $98.55 per month before traffic. Push 2 TB through it and you are at roughly $370 per month. At 10 TB of uploads you are past $1,300 once egress is included.
Where the NAT Gateway cost hides on your bill
Here is a gotcha I did not expect. In Cost Explorer, NAT Gateway usage sits under the EC2-Other service, not under VPC. The usage types are NatGateway-Hours and NatGateway-Bytes. If EC2-Other is climbing, group by usage type next. My recommendation: set a Cost Anomaly Detection alert on EC2-Other today.
Why does S3 traffic drive up NAT Gateway cost?
S3 traffic drives up NAT Gateway cost because, without a gateway endpoint, your VPC treats S3 as an internet destination. The private subnet’s route table sends 0.0.0.0/0 to the NAT Gateway, and the S3 public endpoint falls inside that range. The packets never leave the AWS network, but you are billed as if they did.
The same rule applies to DynamoDB, and indirectly to ECR. Container image layers are stored in S3, so every Fargate task launch or Lambda container pull crosses NAT too. AWS Community Builder Paul Santus documented a striking example in a Bedrock AgentCore cost post-mortem. An idle agent with zero invocations pushed 659 GB through NAT in six days. The cause was a 10-VM warm pool repeatedly pulling a 435 MB container image from ECR. ECR layers live in S3. One free S3 gateway endpoint dropped the charge to near zero.
For PHP teams the pattern is the same, just quieter. Laravel’s S3 filesystem driver, Drupal’s s3fs module and WordPress offload plugins all generate constant S3 traffic. If you already use budget guards on your AI API calls, apply the same discipline to networking. Assume every S3 byte from a private subnet costs $0.045 until you prove otherwise.
How do you find what is using your NAT Gateway?
You find NAT Gateway traffic sources with VPC Flow Logs and a CloudWatch Logs Insights query that sums bytes by source address. AWS documents the exact queries in its re:Post knowledge-center article on NAT top contributors. Here is the process I use.
- Open CloudWatch metrics for the NAT Gateway. Check
BytesInFromDestination(downloads) andBytesOutToSourceto see the direction of the problem. - Enable VPC Flow Logs on the VPC with CloudWatch Logs as the destination. Use the custom format that includes
pkt-srcaddrandpkt-dstaddr. Otherwise NAT traffic shows the gateway’s own IP instead of the real source. - Wait 15 to 20 minutes for data, then run the query below with your NAT Gateway’s private IP and VPC CIDR.
- Resolve the top external IPs against
ip-ranges.amazonaws.com/ip-ranges.json. If they resolve to the S3 service, you have found your fix.
filter (dstAddr in ["10.0.0.144"] AND isIpv4InSubnet(srcAddr, "10.0.0.0/16"))
| stats sum(bytes) as bytesTransferred by srcAddr, dstAddr
| sort bytesTransferred desc
| limit 20
When I ran this on a client’s Laravel API last year, the top three sources were the queue workers. The top destinations were all S3 IPs. Run it before you change anything, so you can prove the saving afterwards.
How do you add an S3 gateway endpoint to cut NAT Gateway cost?
You add a gateway endpoint by creating a VPC endpoint of type Gateway for com.amazonaws.<region>.s3 and associating it with your private route tables. The AWS PrivateLink gateway endpoints documentation confirms there is no additional charge for gateway endpoints. Zero hourly fee, zero per-GB fee.
- In the VPC console, choose Endpoints, then Create endpoint, and select the S3 service with type Gateway.
- Select the VPC and tick every route table used by your private subnets. AWS adds a route whose destination is the S3 prefix list and whose target is the endpoint.
- Repeat for DynamoDB if your app uses it. It is also free.
- Confirm your security groups allow outbound TCP 443 to the S3 prefix list ID. Most default groups already allow all outbound.
- Re-run the flow-log query after an hour. S3 destinations should have vanished from the NAT top-talkers list.
resource "aws_vpc_endpoint" "s3" {
vpc_id = aws_vpc.main.id
service_name = "com.amazonaws.${var.region}.s3"
vpc_endpoint_type = "Gateway"
route_table_ids = [aws_route_table.private.id]
}
One gotcha from the docs: prefix lists are Region-specific, so traffic to a bucket in another Region still goes through NAT. My recommendation is blunt: put an S3 gateway endpoint in every VPC template you own, today. There is no scenario where it costs you anything.
When do interface endpoints cost more than a NAT Gateway?
Interface endpoints cost more than NAT when your traffic to that service is below roughly 209 GB per month per Availability Zone. This is the part most cost-cutting articles skip. Gateway endpoints are free, but interface endpoints (PrivateLink) for services like ECR, CloudWatch, SQS, STS and Secrets Manager are not. They cost $0.01 per hour per AZ plus $0.01 per GB processed.
Do the maths. One interface endpoint in three AZs is $21.90 per month in hourly fees. Its per-GB saving over NAT is $0.035 ($0.045 minus $0.01). So each AZ’s $7.30 monthly charge only pays for itself after about 209 GB of traffic to that service. A low-traffic SQS or STS endpoint will never reach that.
A real re:Post question shows the trap. A developer on ECS Fargate across two AZs priced five endpoints (S3, SSM, ECR API, ECR DKR, CloudWatch). The calculator said $85 per month, versus roughly $65 for two NAT Gateways. After excluding the free S3 endpoint, the interface endpoints came out about $5 cheaper than NAT. One more endpoint would have flipped the result.
The NAT Gateway cost decision rule I use
Always create the S3 and DynamoDB gateway endpoints. Then add an interface endpoint only for services above 200 GB of monthly traffic per AZ, which usually means ECR and CloudWatch Logs. Leave the rest on NAT. For dev and staging, use a single NAT Gateway in one AZ. That alone takes hourly fees from $98.55 to $32.85 per month.
How do PHP apps on Lambda and Fargate hit the NAT Gateway cost trap?
PHP apps hit the trap the moment you attach a Lambda function or Fargate task to private subnets to reach RDS. The function loses direct internet access. So someone adds a NAT Gateway. From then on every S3 call, Composer pull and third-party webhook is metered at $0.045 per GB.
I covered the basics in my earlier post on AWS Lambda functions and VPC configuration. The trade-offs are in server versus serverless architecture. What I did not stress back then is the network bill. On the Laravel project I mentioned, NatGateway-Bytes was 61 percent of the networking line. The queue workers read originals from S3 and wrote four resized variants back. Every read and write crossed NAT. Adding the S3 gateway endpoint took one Terraform resource and one deploy. The next invoice showed the NAT data charge down by 78 percent. Nothing else changed.
// Laravel: nothing changes in code. The saving is purely routing.
// config/filesystems.php still points at the same bucket.
Storage::disk('s3')->put("variants/{$id}/large.webp", $binary);
// Verify from inside the task that S3 resolves to the gateway path:
// aws ec2 describe-route-tables --filters Name=vpc-id,Values=vpc-xxxx \
// --query 'RouteTables[].Routes[?starts_with(DestinationPrefixListId, `pl-`)]'
If you run Drupal or WordPress with an S3 offload module on ECS, check your route tables this week. The fix costs nothing and takes ten minutes.
NAT Gateway cost versus every alternative
| Option | Performance | Complexity | When to Use |
|---|---|---|---|
| NAT Gateway (per AZ) | $0.045/hr plus $0.045/GB; up to 100 Gbps | Low, fully managed | Internet-bound traffic and low-volume AWS services |
| S3 / DynamoDB gateway endpoint | $0/hr, $0/GB; stays on AWS backbone | Very low, one route-table entry | Every VPC with private subnets, no exceptions |
| Interface endpoint (PrivateLink) | $0.01/hr per AZ plus $0.01/GB | Medium, one ENI per AZ, DNS settings | Services above ~209 GB/month per AZ, e.g. ECR, CloudWatch Logs |
| NAT instance (t4g.nano) | About $3/month, no per-GB fee, limited bandwidth | High, self-managed patching and failover | Dev and test environments under 100 GB/month |
| IPv6 egress-only internet gateway | $0/hr, $0/GB processing | Medium, requires dual-stack subnets and IPv6-ready dependencies | Greenfield VPCs with IPv6-capable upstreams |
The NexGismo verdict: Every VPC with a private subnet should have an S3 gateway endpoint and a DynamoDB gateway endpoint on day one, because they are free and remove the largest source of NAT Gateway cost. Do not blindly add interface endpoints for every service; below roughly 209 GB per month per AZ they cost more than the NAT traffic they replace. Run the flow-log query first, fix S3 second, and only then decide on ECR and CloudWatch endpoints.
Key takeaways on NAT Gateway cost
- An AWS NAT Gateway costs $0.045 per hour ($32.85 per month) plus $0.045 per GB processed in both directions, in us-east-1 as of 2026.
- A three-AZ NAT Gateway deployment costs $98.55 per month in hourly fees before any data is processed.
- Uploading 1 GB to the internet from a private subnet costs $0.135: $0.045 NAT processing plus $0.09 data transfer out.
- VPC gateway endpoints for Amazon S3 and DynamoDB have no hourly charge and no data-processing charge, per the AWS PrivateLink documentation.
- An interface endpoint costs $0.01 per hour per AZ plus $0.01 per GB. It only beats NAT Gateway pricing above roughly 209 GB per month per AZ.
- Pulling a container image from ECR privately requires two interface endpoints (ecr.api and ecr.dkr) plus the free S3 gateway endpoint.
- NAT Gateway charges appear under the EC2-Other service in Cost Explorer as usage types NatGateway-Hours and NatGateway-Bytes.
Frequently Asked Questions
How much does a NAT Gateway cost per month?
A single NAT Gateway costs $32.85 per month in hourly charges ($0.045 per hour times 730 hours) in us-east-1. Add $0.045 for every GB processed in either direction. A three-AZ layout with one gateway per zone costs $98.55 per month before traffic. Uploading 500 GB a month adds $22.50 in processing plus $45 in internet egress.
Why is my NAT Gateway bill so high?
Two causes explain almost every high NAT Gateway bill. First, one gateway per Availability Zone across several VPCs multiplies the hourly fee. Second, traffic to S3, DynamoDB, ECR and CloudWatch from private subnets routes through NAT by default at $0.045 per GB. Query VPC Flow Logs for top talkers; S3 IP ranges usually dominate.
Should I use VPC endpoints instead of NAT Gateway?
Always add gateway endpoints for S3 and DynamoDB, because they are free and remove most NAT data charges. For other services, interface endpoints cost $0.01 per hour per AZ plus $0.01 per GB. They only save money above roughly 209 GB per month per AZ. Keep the NAT Gateway for genuine internet traffic and low-volume AWS services.
Are VPC gateway endpoints free?
Yes. AWS charges nothing for gateway endpoints to Amazon S3 and DynamoDB: no hourly fee and no data-processing fee. Standard S3 request and storage pricing still applies. Interface endpoints are different. They use AWS PrivateLink and cost $0.01 per hour per AZ plus $0.01 per GB processed.
How do I find what is using my NAT Gateway?
Check the NAT Gateway’s CloudWatch metrics BytesInFromDestination and BytesOutToSource for direction and timing. Then enable VPC Flow Logs to CloudWatch Logs and run a Logs Insights query that filters on the NAT Gateway’s private IP and sums bytes by source address. Resolve the top external IPs against the published AWS IP ranges file to identify the service.
Final word
NAT Gateway cost is not an AWS pricing scandal. It is a default route doing exactly what you told it to do. The fix is cheap, and the diagnostic is a single Logs Insights query. Teams that pay $30 a month checked the route table before the first invoice. Teams that pay $1,000 did not. Add the gateway endpoints to your VPC module, run the flow-log query on any account older than six months, and apply the 209 GB rule before buying interface endpoints. If you found a surprise in your own NatGateway-Bytes line, share the number with me on LinkedIn.