AWS egress fees for a 10 TB month
Ten terabytes of internet egress from US East (N. Virginia) lists at $912.60: the first 100 GB each month are free and the next 10,140 GB bill at $0.09. Most calculators for AWS egress fees stop at that line. Take a hypothetical invoicing SaaS company, Tallgrass Ledger, running in three Availability Zones in us-east-1. Its 10 TB month came to $1,349.07 in data transfer charges once NAT Gateway processing, traffic between zones, and replication to us-west-2 were priced. Every rate here is a us-east-1 list price checked on September 26 and 27, 2026. Other Regions and negotiated discounts change them.
$1,349.07 for a month that served 10 TB
Tallgrass's private subnets reach S3, Amazon ECR, and public package mirrors through one NAT gateway per zone. Its application servers talk to a self-managed database and cache in other zones, and one S3 bucket replicates to us-west-2. Customer responses leave through the load balancer, so the NAT carries only what the servers fetch.
| Line | Volume | Rate | Monthly |
|---|---|---|---|
| Internet egress | 10,240 GB, less 100 GB free | $0.09/GB | $912.60 |
| NAT Gateway hours | 3 gateways x 730 hours | $0.045/hour | $98.55 |
| NAT Gateway processing | 4,096 GB: 2,560 GB of S3 reads, 1,024 GB of ECR image layers, 512 GB of OS packages and public images | $0.045/GB | $184.32 |
| Cross-AZ | 6,144 GB, billed on both sides | $0.01/GB per side | $122.88 |
| Replication to us-west-2 | 1,536 GB | $0.02/GB | $30.72 |
| Total | $1,349.07 |
Volumes count 1 TB as 1,024 GB, the way AWS counts its tiers. The 100 GB allowance is aggregated across services and Regions, so it comes off once.
The internet line is 67.6 percent of the total. The other four lines add $436.47, and an egress cost calculator that multiplies terabytes by $0.09 prices none of them.
Support fees are computed on these charges too, on the gross amount before any discounts or credits. Business Support+ takes 7 percent of monthly AWS charges between $10,000 and $80,000, so an account in that band pays $94.43 more in support because of these lines. Enterprise Support bills the greater of $5,000 or 10 percent of the first $150,000, so an account past $50,000 a month pays $134.91 more. The whole figure belongs in the infrastructure row of the comparison in Costs beyond your cloud bill.
Where each line lands in Cost Explorer
In the default view by service, NAT hours, NAT processing, and cross-AZ transfer all sit inside EC2 - Other, next to EBS volumes and snapshots, so a review by service shows them as one EC2 line. Each row below maps to a usage type group.
| Line | Usage type group | What trips people up |
|---|---|---|
| Internet egress | EC2: Data Transfer - Internet (Out) | The us-east-1 usage type, DataTransfer-Out-Bytes, has no Region prefix, so a search for USE1 finds nothing. S3 bills its internet transfer under the same usage type name, so group by service when one number matters |
| NAT hours | EC2: NAT Gateway - Running Hours | Billed per gateway per zone, busy or idle |
| NAT processing | EC2: NAT Gateway - Data Processed | Counts bytes in both directions |
| Cross-AZ | EC2: Data Transfer - Inter AZ | Two DataTransfer-Regional-Bytes line items per transfer, so the quantity reads double what VPC Flow Logs count |
| Replication | S3: Data Transfer - Region to Region (Out) | The charge sits on USE1-USW2-AWS-Out-Bytes. The matching USW2-USE1-AWS-In-Bytes line carries no charge |
This pulls August's lines, grouped by usage type:
aws ce get-cost-and-usage \
--time-period Start=2026-08-01,End=2026-09-01 \
--granularity MONTHLY \
--metrics UnblendedCost UsageQuantity \
--group-by Type=DIMENSION,Key=USAGE_TYPE \
--filter '{"Dimensions":{"Key":"USAGE_TYPE_GROUP","Values":[
"EC2: Data Transfer - Internet (Out)",
"EC2: Data Transfer - Inter AZ",
"EC2: Data Transfer - Region to Region (Out)",
"EC2: NAT Gateway - Data Processed",
"EC2: NAT Gateway - Running Hours",
"S3: Data Transfer - Internet (Out)",
"S3: Data Transfer - Region to Region (Out)"]}}'The end date is exclusive. Grouped by usage type, UsageQuantity reads in gigabytes on transfer lines and in hours on NAT hours, enough to rebuild the table above with your own volumes. RDS has its own data transfer groups; add them if databases send data out of the Region. Usage type names shift as AWS adds Regions and features, so check the groups your account shows before scripting against them.
NAT Gateway processing on inbound bytes
The NAT Gateway data processing charge applies to every gigabyte that crosses the gateway, in either direction. AWS's VPC pricing page says it applies "regardless of the traffic's source or destination", with standard data transfer charges on top. Tallgrass's 2,560 GB of S3 reads pay nothing for transfer, since S3 to EC2 in the same Region is free, and $115.20 to cross the NAT. ECR layers and public package downloads carry no inbound transfer charge either, and they still pay $0.045 a gigabyte at the gateway. A team can cut this line without migrating anything.
A NAT gateway in a different zone from the instances it serves adds cross-AZ charges on top, so each zone's private subnets should route to the gateway in their own zone. Tallgrass runs one per zone. A regional NAT gateway spans zones by itself and bills one gateway-hour per zone per hour, so three zones still cost $98.55. It can take up to 60 minutes to expand into a newly used zone, and until then that zone's traffic crosses to another one. Converting from zonal gateways resets open connections, so do it in a maintenance window.
Reading BytesOutToSource in CloudWatch
BytesOutToDestination counts bytes the gateway sends out on behalf of instances. BytesOutToSource counts bytes it hands back to them. Processing bills both, so a gateway whose BytesOutToSource sum dwarfs the other is mostly carrying downloads.
aws cloudwatch get-metric-statistics \
--namespace AWS/NATGateway --metric-name BytesOutToSource \
--dimensions Name=NatGatewayId,Value=nat-0123456789abcdef0 \
--start-time 2026-08-01T00:00:00Z --end-time 2026-09-01T00:00:00Z \
--period 86400 --statistics SumA regional gateway also needs Name=AvailabilityZone,Value=us-east-1a in the dimensions, with one query per zone. To see where the bytes come from, turn on VPC Flow Logs for the gateway's network interface and sum bytes by remote address. Expect AWS's own public endpoints near the top: S3 and ECR, and often CloudWatch Logs from agents shipping logs out of private subnets.
S3 gateway endpoint: $161.28 off the NAT line
Gateway endpoints for S3 and DynamoDB carry no hourly or processing charge. ECR stores image layers in S3, and a pull fetches the manifest from ECR and the layers from S3. One S3 gateway endpoint therefore takes Tallgrass's bucket reads and its layer bytes off the NAT, 3,584 GB a month. NAT processing drops from $184.32 to $23.04, and the monthly total from $1,349.07 to $1,187.79.
aws ec2 create-vpc-endpoint \
--vpc-id vpc-0123456789abcdef0 \
--vpc-endpoint-type Gateway \
--service-name com.amazonaws.us-east-1.s3 \
--route-table-ids rtb-0aaaaaaaaaaaaaaaa rtb-0bbbbbbbbbbbbbbbb rtb-0ccccccccccccccccFour things go wrong on the day it is added:
- Adding the route disconnects open TCP connections to S3, and they do not resume. Schedule it outside a batch window, or confirm the application reconnects.
- Bucket policies that allow by
aws:SourceIp, usually the NAT's Elastic IP, stop matching because S3 now sees private addresses. Rewrite them withaws:VpcSourceIporaws:SourceVpcefirst. - An endpoint policy that lists only your own buckets breaks image pulls. ECR layers come from
prod-us-east-1-starport-layer-bucket, and the policy has to allow it. - Buckets in other Regions stay out of the endpoint's reach, so those reads still cross the NAT.
ECR interface endpoints (ecr.api and ecr.dkr) cost $0.01 an hour each in each zone, $43.80 a month across three zones, plus $0.01 a gigabyte. With the S3 endpoint already carrying the layers, they take only manifest and API calls off the NAT, so they belong in subnets with no NAT at all and rarely pay for themselves on cost.
After the endpoint, Tallgrass's three gateways cost more by the hour ($98.55) than they spend processing ($23.04). Running one zonal gateway saves $65.70 a month in hours. The two zones without a gateway then send their share of the remaining 512 GB across zones, about $6.83 at $0.02 a gigabyte, and outbound access for the whole VPC depends on one zone. Make that call on availability grounds.
EC2 bills both sides of every cross-AZ gigabyte.
Traffic between instances in different zones costs $0.01 a gigabyte on each side, so the cross-AZ data transfer cost is $0.02 for every gigabyte that crosses when both instances sit in the same account. Across accounts, each account pays its own side. Tallgrass sends 6,144 GB across zones a month, which comes to $122.88.
The usual sources are application servers reaching a database or cache primary in another zone, self-managed clusters on EC2 that replicate across zones, such as Kafka or Elasticsearch, and instances routed through a NAT gateway in another zone. VPC Flow Logs, with source and destination addresses mapped to subnets and their zones, show which pairs of instances carry the traffic. When the pairs span accounts, compare zone IDs such as use1-az1, because us-east-1a in one account can be a different physical zone from us-east-1a in another.
Much of this spend is what the application pays to survive losing a zone. Pinning the database, the cache, and the application servers to one zone removes the line and the protection together, so for a small SaaS backend, settle it with the high availability design first. Kafka consumers are the exception. With broker.rack and replica.selector.class set to the rack-aware selector on the brokers, and client.rack on the consumers, each consumer reads from a replica in its own zone, while replication between brokers keeps crossing zones.
A replica in Oregon or Ohio
Replication from us-east-1 to us-west-2 costs $0.02 a gigabyte, and to us-east-2 it costs $0.01. Tallgrass pays $30.72 a month to Oregon and would pay $15.36 to Ohio. S3 Replication Time Control, when enabled, adds $0.015 a gigabyte, another $23.04 here. Whether a Region a few hundred miles away is far enough is a disaster recovery question, and a $15.36 difference should not outweigh the answer.
Get the exit credit approved before the copy starts
AWS free data transfer out for a migration arrives as a temporary credit, approved in advance, with conditions that decide whether a given plan qualifies. The EC2 FAQ gives the fullest version of the terms:
- Ask through AWS Support and say the request is for free data transfer to move off AWS. If you have an account team or a negotiated commitment, talk to them first.
- Wait for approval before copying anything. Bytes moved during a throughput test the week before approval bill at list.
- The credit counts against data transfer out only. AWS sizes it from the volume of all data stored across AWS services at the time it calculates.
- Scope is all data off AWS, or all data off a particular service. By the end of the window, delete the remaining data and workloads from the service or services you left, or close the account.
- AWS may review usage afterward and charge back credited transfer it finds was used for another purpose.
AWS's pages disagree on the window. The EC2 FAQ and the News Blog post, updated September 30, 2025, give 90 days. The Global Network FAQ still says 60 days and requires deleting everything from the account. Get the approved window and scope written into the Support case.
A credit sized once from stored volume shapes how the copy should run. Any transfer that restarts from zero after a failure sends the same bytes twice, and the final catch-up pass before cutover sends changed objects again. Use a tool that skips objects already copied, such as aws s3 sync or rclone, and keep the catch-up pass small. Request charges and the instances running the copy are standard service charges, which the credit excludes.
Because support uses gross charges, a credited transfer still enters the support base. On Business Support+ in the 7 percent band, the $4,917.20 exit transfer priced below adds $344.20 of support even if every byte is credited. Raise it in the same Support case.
Copying 60 TB through the internet tiers
Internet egress tiers aggregate across EC2, S3, RDS, CloudWatch Logs, and a dozen other services within a month, so a bulk copy stacks on top of customer traffic. The price list defines the $0.09 tier as the first 10,240 GB billed beyond the free 100 GB, followed by $0.085 up to 51,200 GB, $0.07 up to 153,600 GB, and $0.05 above. Tallgrass's customer traffic bills 10,140 GB, which leaves 100 GB at $0.09 for anything else that month.
Tallgrass stores 60 TB. Copied out in one month, that is 100 GB at $0.09, 40,960 GB at $0.085, and 20,380 GB at $0.07, for $4,917.20 at list, covered if the credit is approved and the conditions hold. At 80 percent of line rate, 60 TB takes about 7.6 days over 1 Gbps and about 18 hours over 10 Gbps. Reaching that rate takes many parallel object transfers, since one stream from S3 runs far below 10 Gbps, and the receiving side's disks have to keep up. With the copy fitting inside a week, the deletion condition and the cutover plan set the schedule.
Direct Connect at $0.02 a gigabyte
| Path for 60 TB | AWS data out at list | Credit |
|---|---|---|
| Internet, credit approved first | $4,917.20 | Covered |
| Internet, copy started before approval | $4,917.20 | None |
| Direct Connect | $1,228.80 | Excluded |
Direct Connect ports bill on top: a dedicated 1 Gbps port is $0.30 an hour, $219.00 for a month, and 10 Gbps is $2.25 an hour, $1,642.50. Dedicated ports also need a cross connect at the Direct Connect location, so one rarely helps a migration that starts next week. A hosted connection is the usual faster route: a Direct Connect Partner provisions it from a parent connection the partner already runs, and AWS polices it at the ordered speed, dropping traffic above that rate. Snow Family, CloudFront, and Global Accelerator are excluded from the credit as well. Direct Connect costs less than list internet egress and never qualifies for the credit, so it earns its place when the same connection will carry hybrid traffic after the exit. AWS can change the free transfer terms at any time, so recheck them before the figure goes into a budget.
Recurring egress after a QA-only migration
Nobody should move production first. We start customers on dev or QA, usually QA, because it is the least developed stack and a team can pull it back at low risk. In a QA-only migration, production stays on AWS, in the same S3 buckets and databases, so no service is vacated and the credit's deletion condition cannot be met. The first copy of 3 TB of QA data costs $261.62 with no credit: 100 GB at $0.09 and the rest at $0.085, because customer traffic has already used most of the first tier.
The recurring line depends on where each QA stack gets its data. QA turns over faster than dev, because each validation or regression run needs a fresh copy with a specific dataset. If every new stack loads that dataset from S3 in us-east-1, egress grows with the number of stacks. Take a hypothetical 40 stacks a month, each loading 20 GB:
| QA dataset path | Monthly egress | Transfer | Over the VPN |
|---|---|---|---|
| Each stack loads from S3 | 800 GB | $68.50 | $120.30 |
| Weekly refresh of a local copy | 80 GB | $7.20 | $51.80 |
A Site-to-Site VPN connection costs $0.05 an hour, $36.50 a month, and data sent out over it bills at internet egress rates. The S3 gateway endpoint cannot serve traffic arriving over the VPN, so reads over the tunnel need an S3 interface endpoint. It bills $0.01 an hour in each zone it runs in, $7.30 a month for the one zone priced in the table, plus $0.01 a gigabyte. Reads over the internet pay the same egress without either charge. Container images pulled from ECR in us-east-1 count the same way, which makes a registry mirror on the QA side worth setting up. Test results and logs sent back into AWS are free inbound.
Our provisioning sequence builds each stack in order and ends by loading the base users and dataset, so where that dataset sits decides this line. We build hybrid setups that connect cloud and on-premise systems. The dataset's location and refresh schedule belong in the migration plan. If QA needs production-scale data refreshed daily, the recurring line can outgrow what the QA migration was meant to prove, so price it before choosing QA as the first stack to leave.
Who should stay on AWS
AWS can host almost anything well for a team that knows how to assemble it, and for some bills a change of host does little for egress. In these cases we would tell the team to stay.
Most bytes go to the application's own customers. That traffic follows the application to any host, so the comparison needs the new host's bandwidth terms beside AWS's $0.09.
Delivery runs through CloudFront. Origin fetch from AWS origins is waived, CloudFront egress sits outside the exit credit, and an audience served from edge locations around the world fits one data center badly. Petrichor runs in one U.S. data center, and workloads that need more than one facility belong elsewhere.
Managed services hold most of the data. A design that keeps its data in S3 or DynamoDB keeps a hybrid egress line for as long as it runs, and companies built deep into AWS's own services fit Petrichor poorly.
NAT processing and cross-AZ traffic make up most of the extra third. Fix those in place first.
Pull last month's data transfer lines with the Cost Explorer command above and book a call with a consultant.