Compute and storage are the charges you expect. Data transfer is the one that shows up on the bill as a number you cannot immediately explain, because nothing you provisioned is called "data transfer." It is a side effect of how your architecture moves bytes around, and AWS prices it in ways that are easy to trigger by accident. Here are the transfer charges that catch people, roughly what they cost, and how to avoid them.
The mental model: it depends on where the bytes go
AWS data transfer pricing is basically a function of distance. The further data travels and the more boundaries it crosses, the more it costs:
- Within the same Availability Zone, using private IPs: free.
- Between AZs in the same region: charged, typically around $0.01/GB each direction.
- Between regions: charged more, varies by region pair.
- Out to the internet (egress): the big one, tiered, commonly around $0.09/GB and down as volume grows.
- Inbound from the internet: free.
Inbound free, outbound expensive, and every boundary crossing in between costs something. Keep that model and most surprises make sense.
Charge 1: cross-AZ traffic you did not know you had
Spreading across AZs is good for availability. It also means your app in AZ-a talking to your database in AZ-b is paying cross-AZ transfer on every query, both directions. At low volume it is noise. At scale, chatty services split across AZs can rack up a real number purely from internal traffic. It is invisible because it is "just the app working," and no single component looks responsible.
Mitigation: keep tightly-coupled, high-traffic components AZ-aware so the hot path stays within an AZ where you can, without giving up the redundancy you actually need.
Charge 2: the NAT gateway data processing fee
NAT gateways charge per hour to exist and about $0.045 per GB processed. That per-GB fee is easy to forget. If private instances pull large amounts of data through a NAT gateway, for example fetching big artifacts or hitting S3 without a VPC endpoint, you pay NAT processing on all of it.
Mitigation: use VPC endpoints (gateway endpoints for S3 and DynamoDB are free) so that traffic to those services skips the NAT gateway entirely. This is one of the highest-return transfer fixes there is, because S3 traffic through a NAT gateway is pure avoidable cost.
Charge 3: egress to the internet, including to your users
Every byte you serve to the internet is egress, and it is the priciest transfer tier. For a data-heavy or media-heavy application this can become a top line item on its own. The classic mistake is serving large assets directly from S3 or EC2 to users at the raw egress rate.
Mitigation: put a CDN (CloudFront) in front. CloudFront egress is generally cheaper than raw S3/EC2 egress, and transfer from S3 to CloudFront is free, so you cut the per-GB rate and improve latency at the same time.
Charge 4: inter-region replication and chatty cross-region setups
Cross-region replication, multi-region architectures, and services in one region calling data in another all pay inter-region transfer, which is more expensive than cross-AZ. Sometimes this is a deliberate, worth-it cost for DR or latency. Often it is accidental, a resource left in the wrong region, or a dependency nobody meant to make cross-region.
Mitigation: know which cross-region flows are intentional and which are accidents of where something got deployed. The accidental ones are pure waste.
How to find yours
Data transfer hides because it is not a resource you can list. Find it through the bill:
- In Cost Explorer, filter by usage type and look for the transfer usage types (they contain things like
DataTransfer,-Out-Bytes,AWS-Out, regional and NAT processing codes). Group by usage type to see which kind of transfer dominates. - Then trace the biggest category back to the architecture causing it: cross-AZ chatter, NAT processing, internet egress, or inter-region.
Because it is architectural, transfer cost is also something continuous cost tooling should surface and attribute for you rather than making you spelunk usage types every month (that attribution is part of what ZopNight does), but Cost Explorer's usage-type view is the free way to start.
The take
Data transfer is the cost with no resource behind it, which is exactly why it surprises people. The rules are simple once you hold them: inbound free, same-AZ free, every boundary crossing and every byte to the internet costs. The big avoidable wins are VPC endpoints for S3 to skip NAT processing, a CDN for internet egress, and keeping chatty components from paying cross-AZ tolls on the hot path.
What is the transfer charge that surprised you most? For me it was NAT gateway data processing on S3 traffic, invisible until I added a gateway endpoint and watched a line item I had never understood simply drop.
Top comments (0)