AWS Data Transfer Costs Explained: How to Cut Egress Fees

August 10, 2026 Updated FinOps, AWS
AWS Data Transfer Costs: How to Cut NAT and Egress

When I review an AWS bill, the line that most often looks wrong is a NAT Gateway charge that is out of proportion to the application's compute. The instinct is to blame application traffic. More often the cause is the VPC design: how workloads reach AWS services, where container images come from, and how much traffic crosses Availability Zones without anyone deciding it should.

This guide explains how AWS data transfer is billed, walks through a typical NAT Gateway investigation, and lists the fixes in the order I apply them.

Short answer: inbound traffic is free; internet egress, cross-AZ and inter-region traffic are billed per GB; and anything that goes through a NAT Gateway pays an extra processing charge on top. The biggest avoidable costs usually come from AWS-service traffic (S3, ECR, DynamoDB) routed through NAT instead of VPC endpoints, and from chatty services split across AZs.

How AWS data transfer is billed

Rates below are us-east-1 list prices at the time of writing; other regions differ, so check the EC2 data transfer pricing and VPC pricing pages for yours.

PathHow it's billed
Internet to AWS (inbound)Free
Same AZ, private IPFree
Cross-AZ within a regionAbout $0.01/GB in each direction - effectively $0.02/GB for a round trip
Between regionsPer GB, higher than cross-AZ, varies by region pair
AWS to internet (egress)First 100 GB/month free across services, then tiered, starting around $0.09/GB
Through a NAT GatewayAbout $0.045/hour per gateway plus $0.045 per GB processed - on top of any transfer charge
S3 / DynamoDB via gateway endpointNo endpoint charge
Via an interface endpoint (PrivateLink)About $0.01/hour per endpoint per AZ, plus about $0.01 per GB

Two consequences matter more than any single rate. First, NAT processing applies to every gigabyte that passes through the gateway, including traffic to AWS's own services. Second, cross-AZ charges accrue silently on every connection between AZs - service to service, service to database, load balancer to target - and nothing in a default dashboard shows them.

A typical NAT Gateway investigation

An illustrative case, representative of what these investigations find: a SaaS platform spending around $1,500 a month on NAT Gateway processing and related data transfer - far more than its compute bill suggested it should. At $0.045 per GB, that is roughly 30 TB a month flowing through the gateways.

The traffic turned out to have little to do with customers. Three things were driving it:

  1. Container images pulled through NAT. Every node start, scale-out and deployment pulled images from ECR - and ECR stores image layers in S3, so without endpoints all of those bytes went through the NAT Gateway. Images from Docker Hub and other public registries did the same.
  2. AWS service calls through NAT. S3 reads and writes, CloudWatch Logs shipping and other AWS API traffic took the default route out to the internet and back, paying NAT processing on the way.
  3. Cross-AZ traffic. Workloads in one AZ routed through a NAT Gateway in another, and chatty services talked across AZ boundaries, adding cross-AZ charges on top.

The fix had three steps:

  • VPC endpoints for the AWS services that carried the volume - where the economics justified them (see the break-even below). For ECR that means the ecr.api and ecr.dkr interface endpoints and an S3 gateway endpoint, because the layers themselves come from S3 (AWS docs). Public images moved behind an ECR pull-through cache.
  • Workload placement and routing reviewed so each AZ uses its own NAT Gateway and tightly coupled services stop crossing AZ boundaries unnecessarily.
  • Traffic patterns and NAT metrics analysed to find what was left and decide which of it was worth optimising.

The lesson: NAT Gateway costs are not always caused by excessive application traffic. They are often the result of how the VPC is designed and how workloads reach AWS services. That is good news - design problems are usually cheaper to fix than traffic.

How to find where your transfer costs come from

Start in Cost Explorer: filter to EC2-Other and group by Usage Type. The names tell you the path - NatGateway-Bytes is NAT processing, DataTransfer-Regional-Bytes is cross-AZ, DataTransfer-Out-Bytes is internet egress, and inter-region usage types name the region pair.

Then find which gateway is busy. NAT Gateways publish CloudWatch metrics including BytesOutToDestination and BytesInFromDestination:

aws cloudwatch get-metric-statistics \
  --namespace AWS/NATGateway --metric-name BytesOutToDestination \
  --dimensions Name=NatGatewayId,Value=nat-0123456789abcdef0 \
  --start-time 2026-10-01T00:00:00Z --end-time 2026-10-08T00:00:00Z \
  --period 86400 --statistics Sum

Finally, find what the bytes are. Enable VPC Flow Logs on the NAT Gateway's network interface, send them to S3, and rank destinations with Athena. Destination addresses that belong to S3, ECR or other AWS services are traffic a VPC endpoint can take off the NAT.

SELECT dstaddr, SUM(bytes) / 1e9 AS gb
FROM vpc_flow_logs
WHERE interface_id = 'eni-0123456789abcdef0'
GROUP BY dstaddr
ORDER BY gb DESC
LIMIT 20;

When a VPC endpoint pays for itself

Gateway endpoints for S3 and DynamoDB cost nothing, so add them to every VPC with private subnets. Interface endpoints have an hourly charge per AZ, so they need enough traffic to pay off:

  • An interface endpoint in three AZs costs about $0.01 × 730 hours × 3 ≈ $22 a month before data.
  • Each GB it carries saves the $0.045 NAT processing charge but pays $0.01 to the endpoint: a saving of about $0.035/GB.
  • Break-even is therefore roughly 630 GB a month per endpoint (or less if you deploy it in fewer AZs).

That is why "add endpoints for everything" is wrong advice. ECR on a busy Kubernetes cluster clears the bar easily; an endpoint for a service you call a few times an hour never will. For the NAT side of the calculation, the NAT Gateway cost calculator takes your own numbers, and the NAT Gateway cost guide covers the gateway itself in more depth.

Other ways to cut data transfer costs

  1. One NAT Gateway per AZ, with each AZ routing to its own. Routing private subnets in two AZs through one gateway saves an hourly charge and then pays cross-AZ on every byte.
  2. Keep chatty pairs in the same AZ where availability allows. Service-to-cache and service-to-database traffic is the usual cross-AZ volume. On Kubernetes, topology-aware routing keeps service traffic inside a zone when there is enough capacity in each.
  3. Put CloudFront in front of public content. Cached responses don't touch the origin, and data transfer from AWS origins to CloudFront is free.
  4. Compress responses and trim payloads. Fewer bytes are cheaper on every path.
  5. Question cross-region replication. Replicating whole datasets to a second region is a steady inter-region charge; make sure the recovery requirement justifies its scope.
  6. Use PrivateLink for traffic to vendors and other VPCs that support it, instead of the public internet.

Mistakes that keep transfer costs high

  • Treating the NAT bill as an application problem. Check what the bytes are before asking developers to send fewer of them.
  • Adding ECR interface endpoints without the S3 gateway endpoint. The API calls go private; the image layers still go through NAT.
  • Endpoints everywhere, by default. Interface endpoints below break-even cost more than the NAT processing they replace.
  • Spreading tightly coupled services across AZs without counting the traffic. Multi-AZ is right for resilience; it is not free for chatter.

FAQ

Is data transfer within the same AZ free?

Yes, between resources in the same AZ using private IP addresses. Cross-AZ traffic is billed in both directions, and traffic that goes through a NAT Gateway pays NAT processing even when the destination is in the same region.

Why is my NAT Gateway bill so high?

Usually because AWS-service traffic - S3, ECR image pulls, logs - is going through it instead of VPC endpoints, or because subnets in one AZ route through a NAT Gateway in another. Check Cost Explorer for NatGateway-Bytes, then VPC Flow Logs for the destinations.

Do VPC endpoints remove all data transfer charges?

No. Gateway endpoints for S3 and DynamoDB are free and remove NAT processing for that traffic. Interface endpoints have their own hourly and per-GB charges, which are lower than NAT processing per GB but only pay off above a certain volume.

Is inter-region transfer more expensive than cross-AZ?

Yes. Inter-region rates are higher per GB than cross-AZ and vary by region pair, which is why cross-region replication and multi-region architectures deserve a periodic cost review.

Want your transfer costs traced?

Mapping data transfer paths is the first step of every AWS cost optimization engagement I run, because the fixes are usually configuration and the amounts are usually the surprise. The wider method is in the AWS cost optimization guide.

Tags:
Need help with this?

I offer hands-on consulting on exactly this — aws cost optimization consulting .

☁️ AWS Cloud That Saves and Scales

Helping SaaS teams cut costs, speed up releases, and scale securely with DevOps done right

Uncover Bottlenecks & Savings - Free 30-Min Review

Not ready for a call? Get the free AWS Survival Guide instead.

Related Service
AWS Cost Optimization Consulting
Cut your AWS bill by 25–40% - without touching performance or reliability.