S3 egress cost: what AWS data transfer really costs (and how to cut it)
TL;DR. AWS charges roughly $0.09 per GB to move your own data out of S3 to the internet — a rate that has not changed since 2018, even though wholesale bandwidth prices have more than halved in that time (Cloudflare’s analysis; sources below). At 50 TB/month that is about $4,400/month — roughly $53,000 a year — in transfer fees alone, before you pay anything for storage. And 50 TB is not an enterprise number: it’s a small business that found its audience (see the breakdown below). The fee scales with your success. The fix is to move the egress-heavy serving onto infrastructure that doesn’t bill per gigabyte: Cloudflare R2 (no egress fees), Backblaze B2, a CDN like bunny.net, or a flat-rate box on OVH/Hetzner.
First — what does “egress” mean?
Egress is data leaving your cloud — the bytes your service sends out to your users. Every time someone streams your video, downloads your app, or loads your images, that data “egresses” from AWS to them, and AWS meters it per gigabyte.
- Ingress (data coming in — uploads to your servers) is normally free.
- Egress (data going out — what your users receive) is the part that’s metered and expensive.
So “egress fees” are simply what AWS charges you to deliver your own data to your own customers. It’s the cost of being used.
The one number that matters: $0.09/GB, frozen since 2018
S3 storage is cheap and keeps getting cheaper. Egress is where the margin lives. The first-tier internet-egress rate has sat at about $0.09/GB for years. According to Cloudflare’s widely-cited analysis, AWS’s egress fees in North America and Europe have been unchanged since 2018, while wholesale bandwidth in those markets fell by more than half over the same period — and is roughly 93% cheaper than a decade ago, versus AWS egress falling only ~25%. That growing gap between what bandwidth costs and what you’re charged is the most durable line in a cloud bill.
It’s metered, per-gigabyte, and it grows with the one thing you want most — usage. You don’t get a surprise because you did something wrong. You get a surprise because you succeeded.
The freemium trap: when growth makes it worse
If you run a freemium product, egress can turn success into a cash-flow problem. Most of your users are on the free tier. Every one of them who streams a video, downloads a file, or loads your app pulls egress — and pays you nothing. So when a launch goes viral or you hit a growth spurt, your traffic and your bill spike together, while revenue doesn’t follow — because free-to-paid conversion is the hard problem you haven’t fully cracked yet.
Egress is the one major cost that scales with your free users, not your paying ones. That’s the worst cost curve there is: it rises with attention and stays flat with revenue. The more popular you get, the more it hurts. Cutting egress here isn’t just a saving — it’s runway: it buys you the months to figure out conversion before the bill forces the decision for you.
How AWS egress pricing actually works (and where it hides)
Internet egress is tiered (US regions, per AWS’s pricing page, mid-2026 — verify before quoting):
| Monthly egress tier | Price/GB |
|---|---|
| First 100 GB (all services, all regions) | free |
| Up to 10 TB | $0.09 |
| Next 40 TB (10–50 TB) | $0.085 |
| Next 100 TB (50–150 TB) | $0.07 |
| Over 150 TB | $0.05 |
The tier discounts look generous until you notice the other lines that are also egress and rarely get attributed to it:
- NAT Gateway — data through a NAT gateway is charged per GB processed on top of egress. Private subnets pulling from S3 the wrong way quietly double the transfer cost.
- Cross-AZ traffic — moving data between Availability Zones in the same region is billed per GB each way.
- Inter-region replication — copying a bucket to another region is metered transfer.
- S3 → CloudFront — the CDN helps cache-hit egress, but CloudFront’s own rate (~$0.085/GB) is barely cheaper than raw S3, and origin-fetch + request fees still apply.
- Per-request fees — GET/PUT billed per thousand; high-request, small-object workloads stack a second bill.
So the headline $0.09 usually understates your true transfer spend.
How the $53,000 is calculated
Egress is tiered — the first 10 TB is the priciest, then the rate steps down — and AWS bills data transfer in binary gigabytes (1 TB = 1,024 GB). For 50 TB sent out in one month:
| Step | Data | Rate | Cost |
|---|---|---|---|
| Tier 1 — first 10 TB | 10,240 GB | $0.090/GB | $921.60 |
| Tier 2 — next 40 TB | 40,960 GB | $0.085/GB | $3,481.60 |
| One month | 51,200 GB | ~$0.086 blended | ≈ $4,400 / month |
That’s the real figure: about $4,400 per month for 50 TB/month of egress. Multiply by 12 and you get the annual number people quote — ≈ $52,800 ≈ $53,000 per year. (Using decimal gigabytes, 1 TB = 1,000 GB, it’s ~$4,300/month → ~$51,600/year — same ballpark.)
This is transfer only. Storage (~$1,150/month for 50 TB on S3 Standard), request fees, and any NAT-gateway / cross-AZ / inter-region transfer are all extra. $4,400/month is the floor for the egress line, not the whole bill.
What does 50 TB a month actually look like?
50 TB (≈ 50,000 GB) of egress sounds abstract, so here’s what it is in the real world. It is not a hyperscale operation — it’s a small/scale-up business that’s working:
- Video — HD (1080p) streaming uses about 3 GB per hour (Netflix’s own figure). 50,000 GB ÷ 3 ≈ 16,700 hours of video served a month — roughly 1,700 viewers each watching 10 hours, or about 550 people watching one hour a day. A modest course platform, fitness-streaming app, or niche media service.
- Downloads — a 100 MB app, dataset, or media file downloaded 500,000 times a month.
- A content/media site — pages weighing ~2 MB at 25 million pageviews a month.
- A podcast / audio host — a 50 MB episode with 1 million downloads a month.
Any one of those is an ordinary, healthy business. And on S3, each pays about $4,400 a month — roughly $53,000 a year — just to deliver content it already produced and stored.
What S3 egress costs at every scale
Pure transfer-out cost, S3 to the internet, before storage or requests, vs the alternatives that don’t meter egress the same way. Approximate, mid-2026 — verify before quoting.
| Egress / month | Amazon S3 → internet | Cloudflare R2 | bunny.net CDN | OVH / Hetzner flat box |
|---|---|---|---|---|
| 1 TB | ~$92 | $0 | ~$5–10 | $0 (included) |
| 5 TB | ~$460 | $0 | ~$25–50 | $0 |
| 10 TB | ~$920 | $0 | ~$50–100 | $0 |
| 50 TB | ~$4,400 | $0 | ~$250–500 | $0 |
| 100 TB | ~$8,000 | $0 | ~$500–1,000 | $0 |
| 500 TB | ~$29,500 | $0 | ~$2,500–5,000 | $0 (dedicated, unmetered) |
At 50 TB/month, that AWS column is ~$4,400/month — about $53,000/year — for transfer alone. The same bytes cost $0 in egress on R2, a few hundred dollars on a CDN, or nothing on a flat-rate server you already rent.
The honest footnote. This table is egress only. R2 and B2 still charge for storage (~$15/TB and ~$6/TB per month); a flat box still costs rent plus the time to run it. Egress is simply the line where AWS’s markup is most extreme and most avoidable — which is why it’s almost always the first thing worth moving.
The four ways to cut S3 egress (in order of effort)
- Put a cache in front (lowest effort). A CDN serves repeat requests from cache, so they never touch S3 egress. Cloudflare’s free tier gives unmetered cache-hit bandwidth for normal sites; bunny.net (~$0.005–0.01/GB) is excellent for media. This alone removes most of the bill without moving any data.
- Move the bucket to zero-egress storage. Cloudflare R2 is S3-compatible with no egress fees; Backblaze B2 gives free egress up to 3× stored data. Both speak the S3 API — usually a config change.
- Serve the heavy traffic from a flat-rate box. OVH and Hetzner include generous/unlimited transfer; see Migrate off MinIO for the self-hosted storage side.
- Fix the hidden internal egress. Add S3 VPC Gateway Endpoints (free) so S3 traffic skips the NAT gateway; collapse needless cross-AZ chatter. Free, and worth doing even if you keep everything on AWS.
When S3 egress is genuinely fine (don’t move it)
- Low egress (a few hundred GB/month) — the bill is small; not worth a migration.
- Spiky, unpredictable traffic that truly benefits from scale-to-zero and global presence.
- Deep in-region AWS integration — if data is consumed by other AWS services in-region (no internet egress), you’re not paying the $0.09; the fix there is the free VPC-endpoint cleanup, not a move.
The point is never “AWS bad.” It’s: egress is the line where you’re most overcharged, and usually the easiest to cut. Sometimes the answer is a free VPC endpoint plus a CDN, and you keep the bucket where it is.
Quick wins you can do this week
- Open Cost Explorer, group by usage type, find every line with
DataTransfer,NatGateway,Requests. - Add S3 VPC Gateway Endpoints (free) to stop S3 traffic crossing the NAT gateway.
- Put a CDN in front of public, cacheable objects.
- If egress is large and growing, price R2/B2 or a flat box against that annual number.
Your egress line is exactly the line I pull apart in a Cloud-Exit Assessment — a fixed-price, decision-ready report with the real numbers and a target design. Or send me a recent cloud bill and I’ll break out the egress and estimate your annual saving in 24 hours, free. Read by me, never shared.
Sources
- AWS S3 / EC2 data-transfer-out pricing (the $0.09/GB tier and the 100 GB free allowance): AWS pricing pages — aws.amazon.com/s3/pricing and aws.amazon.com/ec2/pricing/on-demand (Data Transfer section).
- “Unchanged since 2018,” wholesale bandwidth “more than halved” / “~93% cheaper over a decade vs AWS ~25%”: Cloudflare, “AWS’s Egregious Egress” — blog.cloudflare.com/aws-egregious-egress/.
- HD (1080p) ≈ 3 GB/hour: Netflix Help Center (data-usage settings), corroborated by multiple independent measurements.
- R2 (zero egress), B2 (free egress to 3× stored), bunny.net (~$0.005–0.01/GB), OVH/Hetzner (included traffic): the respective provider pricing pages.