AWS Builder Center
Why Serving Files Directly from Amazon S3 Is Costing You 3x More (and Killing Performance)

Why Serving Files Directly from Amazon S3 Is Costing You 3x More (and Killing Performance)

When building web applications, APIs, or static asset storage, the default pattern for most developers is simple: create an Amazon S3 bucket, upload assets, and generate public URLs or presigned download links. It works, but at scale, it introduces a severe financial and architectural penalty: S3 Data Transfer Out (DTO) is expensive, un-cached, and subject to geographic latency penalties.

Systems Engineer | Software & Data Solutions
The Hidden Financial Leak: S3 Data Transfer Out
Amazon S3 is an object storage service, not a content delivery network. When end users download objects directly from an S3 bucket:
  1. Full Regional Data Transfer Fees Apply: In most regions (like us-east-1), S3 Data Transfer Out to the internet starts at $0.09 per GB.
  2. Every Hit Equals a Paid GET Request: Each download triggers an s3:GetObject API request ($0.0004 per 1,000 requests).
  3. High Round-Trip Latency: A user in Sydney downloading a 50 MB asset from a bucket in Virginia must traverse the global internet for every byte, degrading performance and increasing connection drops.
1
2
3
4
[User in Sydney / London / Tokyo]
│
▼ ($0.09/GB S3 Data Transfer Out + High Global Latency)
[Amazon S3 Bucket (us-east-1)]
If your application serves 20 TB of media, images, or client downloads per month directly from S3, you are paying $1,800/month purely in data egress, plus hundreds of thousands of individual GET requests.

The Architecture Fix: Fronting S3 with CloudFront

By placing Amazon CloudFront directly in front of your S3 bucket, you change the economics and network topology entirely:
  • S3-to-CloudFront Transfer is 100% Free: Traffic moving from an Amazon S3 bucket to CloudFront edge locations incurs $0.00 per GB in regional data transfer.
  • Cheaper Bandwidth Tiers + Generous Free Tier: CloudFront includes 1 TB of free data transfer out every month, and subsequent usage tiers start lower than S3's baseline egress rates.
  • Aggressive Edge Caching: Popular assets are served directly from hundreds of CloudFront Points of Presence (PoPs) worldwide, dropping TTFB (Time to First Byte) by up to 80% and eliminating upstream s3:GetObject charges on cache hits.
1
2
3
4
5
6
7
[Global User]
│
▼ (Sub-millisecond Edge Response)
[CloudFront Edge PoP] ──(Cache Hit: $0 S3 Fetch)
│
▼ (Origin Cache Miss: $0 S3 Egress)
[Amazon S3 Bucket (Private / No Public Access)]

Locking Down S3: Origin Access Control (OAC)

Never leave the S3 bucket publicly open when using CloudFront. Use Origin Access Control (OAC) to ensure that files can only be fetched through the CloudFront distribution:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
# 1. CloudFront Origin Access Control
resource "aws_cloudfront_origin_access_control" "oac" {
name = "s3-oac"
origin_access_control_origin_type = "s3"
signing_behavior = "always"
signing_protocol = "sigv4"
}

# 2. S3 Bucket Policy Enforcing CloudFront Access Only
resource "aws_s3_bucket_policy" "cdn_bucket_policy" {
bucket = aws_s3_bucket.media.id

policy = jsonencode({
Version = "2012-10-17"
Statement = [
{
Sid = "AllowCloudFrontServicePrincipalReadOnly"
Effect = "Allow"
Principal = { Service = "cloudfront.amazonaws.com" }
Action = "s3:GetObject"
Resource = "${aws_s3_bucket.media.arn}/*"
Condition = {
StringEquals = {
"AWS:SourceArn" = aws_cloudfront_distribution.cdn.arn
}
}
}
]
})
}

Key Takeaways for Builders

  • Never use S3 URLs in frontend apps: Serve static media, downloadable docs, and frontend bundles exclusively through a CloudFront custom domain.
  • Leverage the 1 TB Perpetual Free Tier: Small-to-midsize workloads often run their entire content delivery tier for $0.
  • Block all public access on the bucket: Enable S3 Block Public Access entirely; OAC will authenticate requests cleanly via SigV4 behind the scenes.

Community Check

Are you currently serving downloads directly from S3 or caching them behind CloudFront with OAC? What's your average cache hit ratio? Share your setups below! 👇
#amazon-s3 #amazon-cloudfront #finops #aws-cost-optimization #cloud-architecture
Any opinions in this article are those of the individual author and may not reflect the opinions of AWS.
Enjoyed reading this content? Let the author know!

Your likes, comments, shares, and saves help creators reach more builders.

Loading recommendations

Loading article