Open Calculator

Eliminating AWS NAT Gateway Processing Fees: Gateway VPC Endpoints vs Interface PrivateLink Routing

Published June 19, 2026 · Updated September 08, 2026 · VPC Route Engineering & Flow Log Audits

In standard AWS Virtual Private Cloud (VPC) architectures, EC2 instances, ECS tasks, and EKS Kubernetes pods run inside private subnets without public IPv4 addresses. To reach external endpoints—including AWS's own public regional APIs (`s3.us-east-1.amazonaws.com`, `ecr.dkr.us-east-1.amazonaws.com`, `logs.us-east-1.amazonaws.com`)—traffic is routed by default through a managed **AWS NAT Gateway** residing in a public subnet.

Because AWS NAT Gateways charge a mandatory **$0.045 per GB Data Processing Fee** ($45.00 per TB) on top of hourly instance fees—even when communicating with an S3 bucket in the exact same region and account—unconfigured VPCs routinely waste thousands of dollars per month processing internal storage traffic through NAT Gateways.

Anatomy of the AWS NAT Gateway Cost Structure

A highly available 3-Availability-Zone VPC deploying one managed NAT Gateway per AZ incurs three compounding cost layers:

// Monthly NAT Gateway Cost Equation (US-East / EU-Central)
Fixed_Hourly_Cost = 3 AZs × 730 hours × $0.045/hr = $98.55 / month
NAT_Processing_Cost = Total_Bytes_Through_NAT_GB × $0.045 / GB ($45.00 / TB)
Cross_AZ_NAT_Penalty = $0.020 / GB (If a pod in AZ-b routes through a single NAT in AZ-a)

If an EKS cluster or Spark data pipeline reads and writes 120 TB/month to an S3 bucket in the same region without a VPC Endpoint, S3 itself charges $0.00/GB for same-region transfer—yet the NAT Gateway bills **$5,400.00/month** ($120,000\text{ GB} \times \$0.045$) simply for translating private IP packets to S3's public IP range.

Gateway VPC Endpoints vs. Interface VPC Endpoints (PrivateLink)

AWS provides two distinct mechanisms to bypass NAT Gateways and keep traffic on the private AWS network fabric:

Specification Gateway VPC Endpoint Interface VPC Endpoint (PrivateLink)
Supported AWS Services Amazon S3 & Amazon DynamoDB Only 100+ Services (ECR, CloudWatch Logs, STS, KMS, SQS, Kinesis, S3)
Network Mechanism VPC Route Table Prefix List (`pl-63a5400a`) Elastic Network Interface (ENI) with Private IP + Split-Horizon DNS
Hourly Endpoint Fee $0.00 / hour (100% Free) $0.01 / hour per AZ ($7.30/mo per AZ)
Per-GB Data Processing Fee $0.00 / GB (100% Free) $0.01 / GB (First 1 PB/mo)
Cross-VPC / On-Prem VPN Reachable No (Strictly local VPC route tables) Yes (Reachable via Direct Connect, VPN, and Transit Gateway)

Breakeven Math for Interface VPC Endpoints (ECR, CloudWatch Logs, STS)

While S3 and DynamoDB Gateway Endpoints are 100% free and should be provisioned in every VPC on Day 1, **Interface VPC Endpoints** (used to pull Docker container images from Amazon ECR or ship logs to CloudWatch without hitting the NAT Gateway) cost **$0.01/hour per Availability Zone** ($21.90/month for a 3-AZ deployment) plus **$0.01/GB** processed (saving $0.035/GB compared to the NAT Gateway's $0.045/GB fee).

Monthly Savings per GB Routed via PrivateLink: $0.045 (NAT) - $0.010 (PrivateLink) = $0.035 / GB
3-AZ Interface Endpoint Fixed Cost: 3 AZs × 730 hrs × $0.01 = $21.90 / month
Breakeven Traffic Volume: $21.90 / $0.035 = 625.7 GB / month per service

Important ECR Container Pull Rule: When Kubernetes nodes pull Docker image layers from Amazon ECR, the small manifest authentication call hits `ecr.api` and `ecr.dkr`, but the actual multi-gigabyte container layer blobs are stored in an AWS-managed **S3 bucket**! Therefore, simply adding the free **S3 Gateway VPC Endpoint** eliminates 98% of ECR container pull NAT charges without even needing the paid `ecr.dkr` Interface Endpoint.

Production Terraform HCL: Free S3 & DynamoDB Gateway Endpoints

Attach the following Terraform resources to all private route tables in your VPC to immediately drop S3 and DynamoDB NAT Gateway processing charges to `$0.00`:

resource "aws_vpc_endpoint" "s3_gateway" {
  vpc_id            = aws_vpc.production.id
  service_name      = "com.amazonaws.${var.aws_region}.s3"
  vpc_endpoint_type = "Gateway"

  # Attach to all Private Subnet Route Tables
  route_table_ids = aws_route_table.private[*].id

  tags = {
    Name        = "prod-s3-gateway-endpoint"
    CostCenter  = "zero-nat-bypass"
  }
}

resource "aws_vpc_endpoint" "dynamodb_gateway" {
  vpc_id            = aws_vpc.production.id
  service_name      = "com.amazonaws.${var.aws_region}.dynamodb"
  vpc_endpoint_type = "Gateway"

  route_table_ids = aws_route_table.private[*].id

  tags = {
    Name        = "prod-dynamodb-gateway-endpoint"
    CostCenter  = "zero-nat-bypass"
  }
}

Auditing NAT Gateway Traffic Leaks with VPC Flow Logs

If your NAT Gateway `BytesOutToDestination` CloudWatch metric remains high after deploying Gateway Endpoints, enable v5 VPC Flow Logs (`${interface-id} ${srcaddr} ${dstaddr} ${pkt-srcaddr} ${pkt-dstaddr} ${bytes}`) on the NAT Gateway Elastic Network Interface (`eni-0a8b...`) and execute this CloudWatch Logs Insights query to rank the top destination IPv4 prefixes billing `$0.045/GB`:

# CloudWatch Logs Insights Query: Top Destination IPs Traversing NAT Gateway ENI
filter interfaceId = "eni-0a8b9412c7e102941" and action = "ACCEPT"
| stats sum(bytes)/1000000000 as Total_GB by pktDstAddr
| sort Total_GB desc
| limit 5

# Sample Diagnostic Output (Before Attaching S3 Route Table Entry to Worker Subnet 3):
# pktDstAddr        Total_GB   Service Resolution (via ip-ranges.json)
# 52.217.104.198    4,812.40   AMAZON S3 (us-east-1) -> Missed Private Route Table!
# 54.239.28.85      1,120.15   AMAZON DYNAMODB (us-east-1) -> Missed Private Route Table!
# 3.218.180.12        184.20   External SaaS Telemetry Ingest

In the audit above, one newly created EKS worker node subnet (`private-subnet-us-east-1c-gpu`) had been associated with a secondary VPC route table that lacked the `vpce-0192...` prefix-list entry—causing `5,932 GB` of local S3 and DynamoDB traffic to silently route through the NAT Gateway for `$266.96` in avoidable processing fees.

Audit Small-File Object Storage API Costs Next

Learn why storing millions of 4 KB files inflates Class A PUT and LIST request invoices by 10x+.

API Request Pricing Guide →