The $0.045/GB Mistake Hiding in Almost Every AWS VPC
A NAT Gateway will happily bill you to reach a free AWS service
Here's an AWS billing fact that catches almost everyone eventually: a NAT Gateway charges $0.045 per GB processed, in both directions, for everything that flows through it — including traffic to other AWS services in the same region, like S3 and DynamoDB.
Those two services also offer a free way to reach them from inside a VPC: a Gateway VPC Endpoint. It costs nothing to create, nothing per hour, and nothing per GB. It just needs to exist and be attached to the right route tables.
If it doesn't exist, none of that traffic disappears — it just quietly reroutes through the NAT Gateway instead, at $0.045/GB, forever, until someone notices. This is well-known enough in the AWS community to have a nickname: the $1,000 AWS mistake. It's rarely a single mistake, though. It's usually a missing checkbox from the original VPC setup, silently compounding every month since.
Why this specific gap is so persistent
A few things make this one unusually sticky compared to other cost issues:
- Nothing breaks. Requests to S3 and DynamoDB succeed exactly the same way whether they go through a Gateway Endpoint or a NAT Gateway. There's no error, no latency cliff, no CloudWatch alarm — just a bigger number on next month's bill.
- It's invisible in the AWS Cost Explorer service breakdown. The charge shows up under "EC2-Other" / NAT Gateway data processing, not attributed to S3 or DynamoDB. Unless you already know to look for it, there's no line item that says "you're paying NAT fees for S3 traffic."
- It's per-VPC, and most accounts have more than one VPC. A team that fixed this once, in one VPC, two years ago, can still be bleeding money in every VPC created since — a new environment, a new microservice's dedicated VPC, an acquired team's infrastructure that was never audited.
- It scales with your success. The more traffic your application sends to S3 or DynamoDB, the bigger this line item gets — completely disconnected from whether your infrastructure is efficient. A well-architected, right-sized, "no waste anywhere else" account can still be paying this tax at scale.
What it looks like when a scanner catches it
GreenOps Scan's vpc-endpoints module checks every VPC that has a NAT Gateway for
missing S3/DynamoDB Gateway Endpoints, and pulls the NAT Gateway's actual
BytesOutToDestination / BytesInFromDestination CloudWatch metrics over the last 30
days to estimate what's realistically at stake:
- severity: HIGH
module: VPC-ENDPOINTS
resource: vpc-0a1b2c3d4e5f6a7b8
resourceType: VPC
issue: NAT Gateway present with no S3 Gateway Endpoint — S3 traffic pays NAT data processing fees ($0.045/GB), ~412.6 GB processed by NAT in last 30 days
costSavings: $18.57/mo
confidence: LOW
co2Savings: 0.00 kg/mo
recommendation: Add a free VPC Gateway Endpoint for S3 so traffic routes directly instead of through the NAT Gateway. This is the exact mistake behind the well-known "$1,000 AWS bill" (missing S3 Gateway Endpoint routes S3 traffic through NAT).
That's an illustrative shape, not a specific account's real numbers — the actual
dollar figure depends entirely on how much of a VPC's NAT-processed traffic is
S3/DynamoDB-bound versus genuinely external, which is why the confidence is reported
as low: it's an upper bound estimate from total NAT throughput, not a guarantee. A
busy production VPC pushing serious S3 traffic — log ingestion, backups, static asset
uploads, data pipeline output — can post a number an order of magnitude higher than
that.
The fix costs nothing and breaks nothing
This is one of the rare cost findings with essentially zero downside to fixing:
aws ec2 create-vpc-endpoint \
--vpc-id vpc-0a1b2c3d4e5f6a7b8 \
--service-name com.amazonaws.eu-central-1.s3 \
--vpc-endpoint-type Gateway \
--route-table-ids rtb-0123456789abcdef0
- It's additive — creating a Gateway Endpoint doesn't remove or reconfigure your NAT Gateway. Nothing else changes.
- It's free — no hourly charge, no per-GB charge, ever, for Gateway Endpoints specifically (this is different from Interface Endpoints, which do have an hourly cost — Gateway Endpoints for S3 and DynamoDB are the free kind).
- It's low-risk — the only thing worth reviewing afterward is the endpoint's default access policy, if your account needs tighter control than "anything in this VPC can reach any bucket/table it has IAM permission for."
There's no migration, no downtime, no application change. You add the endpoint, attach it to the route tables that matter, and the next request just takes the cheaper path.
Why this is worth checking even if you're sure you already fixed it
If your team has been on AWS for a while, there's a reasonable chance someone already added the S3 Gateway Endpoint to your main production VPC, years ago, after reading a similar post. That doesn't mean the account is covered:
- Every new VPC — a fresh environment, a new region, a per-team or per-service VPC in a more segmented account — starts from zero and needs the endpoint added again.
- DynamoDB is easy to miss even when S3 is covered, since it's a separate Gateway Endpoint service name, not bundled with the S3 one.
- Accounts that grew through acquisitions, terraform-module copy/paste, or infrastructure inherited from a team that's moved on are the most likely to have silent gaps, because there's no single person who remembers whether it was ever checked.
The check itself takes seconds per VPC: does a NAT Gateway exist, and if so, do Gateway VPC Endpoints for S3 and DynamoDB exist and route through the same route tables. GreenOps Scan runs this automatically as part of a normal read-only scan across every VPC in the account:
npx greenops-scan --modules vpc-endpoints
If nothing shows up, that's not a wasted five minutes — that's confirmation your account isn't paying a tax that a large fraction of AWS accounts still are, without anyone noticing.
Tags: #AWS #CloudCostOptimization #FinOps #VPC #NATGateway #NetworkCosts #GreenOps
