BloggenCloud & Infrastructure
Cloud & Infrastructure

Cloud Egress Fees Explained: How to Stop Paying $0.09/GB to Send Your Own Data

Cloud egress fees are one of the most misunderstood and underestimated costs in cloud computing. A 1PB/month data platform can pay $92,000/month just in AWS egress fees. This guide explains exactly how egress pricing works, where the hidden costs are, and 12 strategies to dramatically reduce data transfer costs.

A

Alex Thompson

CEO & Cloud Architecture Expert at ZeonEdge with 15+ years building enterprise infrastructure.

April 2, 2026
blogDetail.minRead

The Egress Fee Problem

Ingress (data coming into the cloud) is free. Egress (data leaving the cloud) costs $0.09/GB on AWS. This asymmetry is intentional — cloud providers profit from keeping your data inside their network and charge you to move it out. When analysts call cloud egress fees "the modern data tax," they are not being hyperbolic.

At 100TB/month, egress alone costs $9,216. At 1PB/month (not unusual for video, gaming, or data platform companies), that is $92,160/month just in data transfer fees — before you pay for compute, storage, or any actual services. The Bandwidth Alliance, a coalition of cloud providers and CDNs, has been pushing for egress fee reform, but meaningful change has been slow.

AWS Egress Pricing Breakdown

AWS Data Transfer OUT to Internet (us-east-1):
  First 100GB/month:         FREE
  Next 9.9TB (up to 10TB):   $0.09/GB  = $921.60 for 10TB
  Next 40TB (up to 50TB):    $0.085/GB = $3,400 for 40TB
  Next 100TB (up to 150TB):  $0.07/GB  = $7,000 for 100TB
  Over 150TB:                $0.05/GB

AWS Data Transfer within same region:
  Same AZ (EC2 to EC2):      FREE
  Different AZ:              $0.01/GB EACH DIRECTION = $0.02/GB round trip
  To CloudFront (origin):    FREE (CloudFront charges for edge delivery)
  To S3 (same region):       FREE
  EC2 to ECR (same region):  FREE if using VPC endpoint

AWS cross-region transfer:
  EC2 to EC2 different region: $0.02/GB
  S3 cross-region replication: $0.02/GB (plus S3 replication fee)

CloudFront pricing (edge delivery):
  First 10TB/month:          $0.0085/GB  (94% cheaper than direct EC2 egress!)
  Next 40TB:                 $0.0080/GB
  Next 100TB:                $0.0060/GB
  Over 5PB:                  $0.0025/GB

CloudFront vs Direct EC2 at 100TB:
  Direct: $7,700
  CloudFront: $770
  Savings: $6,930 (90%)

Where Hidden Egress Costs Hide

# Cross-AZ traffic is the most commonly overlooked cost
# Every microservice call that crosses AZs = $0.02/GB

# Example: Load-balanced API calls
# ALB distributes traffic across 3 AZs
# Each request crosses AZ boundary: ~50KB payload = $0.000001 per request
# At 100M requests/day: $100/day = $3,000/month just for cross-AZ API traffic!

# Fix: Use topology-aware routing in Kubernetes
# Service TopologyAwareHints tells kube-proxy to prefer same-AZ pods

apiVersion: v1
kind: Service
metadata:
  name: my-service
  annotations:
    service.kubernetes.io/topology-mode: Auto  # Prefer same-zone endpoints
spec:
  selector:
    app: my-app
  ports:
    - port: 80

# NAT Gateway hidden cost:
# Each AZ should have its own NAT Gateway for HA
# But all outbound traffic to internet flows through NAT: $0.045/GB
# At 10TB/month: $460/month just for NAT processing (plus gateway fee)

# Find your NAT Gateway costs
aws ce get-cost-and-usage   --time-period Start=2026-02-01,End=2026-03-01   --granularity MONTHLY   --filter '{"Dimensions": {"Key": "SERVICE", "Values": ["Amazon Virtual Private Cloud"]}}'   --metrics BlendedCost   --output table

Strategy 1: CloudFront for All User-Facing Traffic

resource "aws_cloudfront_distribution" "main" {
  enabled             = true
  is_ipv6_enabled     = true
  default_root_object = "index.html"
  price_class         = "PriceClass_100"  # US/Europe only = lower cost

  origin {
    domain_name = aws_alb.main.dns_name
    origin_id   = "ALB-origin"

    custom_origin_config {
      http_port              = 80
      https_port             = 443
      origin_protocol_policy = "https-only"
      origin_ssl_protocols   = ["TLSv1.2"]
    }
  }

  default_cache_behavior {
    target_origin_id       = "ALB-origin"
    viewer_protocol_policy = "redirect-to-https"
    
    cache_policy_id          = aws_cloudfront_cache_policy.optimized.id
    origin_request_policy_id = data.aws_cloudfront_origin_request_policy.all_viewer.id
    
    allowed_methods = ["DELETE", "GET", "HEAD", "OPTIONS", "PATCH", "POST", "PUT"]
    cached_methods  = ["GET", "HEAD"]
    compress        = true  # Gzip/Brotli reduces transfer size 60-80%
  }
  
  # Cache API responses that are safe to cache
  ordered_cache_behavior {
    path_pattern           = "/api/v1/products*"
    target_origin_id       = "ALB-origin"
    viewer_protocol_policy = "https-only"
    
    cache_policy_id = aws_cloudfront_cache_policy.api_cache.id
    allowed_methods = ["GET", "HEAD"]
    cached_methods  = ["GET", "HEAD"]
  }
}

resource "aws_cloudfront_cache_policy" "api_cache" {
  name        = "api-cache-5min"
  min_ttl     = 0
  default_ttl = 300  # 5 minutes default cache
  max_ttl     = 3600

  parameters_in_cache_key_and_forwarded_to_origin {
    cookies_config { cookie_behavior = "none" }
    headers_config { header_behavior = "none" }
    query_strings_config {
      query_string_behavior = "whitelist"
      query_strings { items = ["page", "limit", "sort"] }
    }
    enable_accept_encoding_gzip   = true
    enable_accept_encoding_brotli = true
  }
}

Strategy 2: VPC Endpoints — Eliminate NAT for AWS Services

# Traffic to AWS services (S3, DynamoDB, SQS, etc.) goes through NAT by default
# VPC endpoints route traffic within AWS network — no NAT, no egress charge

# Calculate potential NAT Gateway savings first
# Find all NAT Gateway charges
aws cloudwatch get-metric-statistics   --namespace AWS/NATGateway   --metric-name BytesOutToDestination   --dimensions Name=NatGatewayId,Value=nat-xxxxxxxxx   --start-time 2026-02-01T00:00:00Z   --end-time 2026-03-01T00:00:00Z   --period 2592000   --statistics Sum

# Create gateway endpoints (FREE for S3 and DynamoDB)
aws ec2 create-vpc-endpoint   --vpc-id vpc-xxxxx   --service-name com.amazonaws.us-east-1.s3   --route-table-ids rtb-xxxxx rtb-yyyyy

aws ec2 create-vpc-endpoint   --vpc-id vpc-xxxxx   --service-name com.amazonaws.us-east-1.dynamodb   --route-table-ids rtb-xxxxx rtb-yyyyy

# Interface endpoints for other services (charged at $0.01/hr + $0.01/GB — but cheaper than NAT)
aws ec2 create-vpc-endpoint   --vpc-endpoint-type Interface   --vpc-id vpc-xxxxx   --service-name com.amazonaws.us-east-1.sqs   --subnet-ids subnet-xxxxx   --security-group-ids sg-xxxxx

Strategy 3: S3 Transfer Acceleration Only When Needed

# S3 Transfer Acceleration: speeds up uploads from distant clients
# Cost: $0.04-0.08/GB ON TOP of normal S3 egress
# Only use it if you have proved global latency problems

# Test if Transfer Acceleration actually helps for your use case
aws s3api create-bucket --bucket perf-test-bucket --region us-east-1
aws s3api put-bucket-accelerate-configuration   --bucket perf-test-bucket   --accelerate-configuration Status=Enabled

# Compare speeds
time aws s3 cp large-file.bin s3://perf-test-bucket/  # Without acceleration
time aws s3 cp large-file.bin s3://perf-test-bucket/   --endpoint-url https://perf-test-bucket.s3-accelerate.amazonaws.com  # With

# If Transfer Acceleration only gives 10-20% improvement, cost rarely justifies it
# If improvement is 2-3x for globally distributed users: may be worth it

# Alternative: CloudFront with S3 origin
# Uploads via CloudFront's edge network to S3 — free acceleration-like behavior
# And CloudFront charges less than S3 Transfer Acceleration

Strategy 4: Compress Everything

# Nginx: enable gzip compression — reduces text/JSON transfer by 60-80%
# Less data transferred = less egress cost

gzip on;
gzip_vary on;
gzip_proxied any;
gzip_comp_level 6;
gzip_buffers 16 8k;
gzip_http_version 1.1;
gzip_min_length 1024;
gzip_types
  text/plain
  text/css
  text/xml
  text/javascript
  application/json
  application/javascript
  application/xml
  application/xml+rss
  application/vnd.ms-fontobject
  application/x-font-ttf
  font/opentype
  image/svg+xml
  image/x-icon;

# Brotli (better compression than gzip, supported by all modern browsers)
# Requires nginx-module-brotli
brotli on;
brotli_comp_level 6;
brotli_types text/plain text/css application/json application/javascript;

# For API responses: if you return JSON with lots of repeated keys, 
# 100KB response compresses to ~15KB = 85% egress reduction

Strategy 5: Multi-Region Architecture — Use CloudFront Regional Edge

Pattern: Serve users from the nearest CloudFront edge, not your origin

Without CloudFront:
  User in Tokyo requests US-East-1 API: 
  - 180ms latency
  - $0.09/GB egress from EC2 in us-east-1
  - Total for 1TB Tokyo traffic: $92

With CloudFront edge + Lambda@Edge or CloudFront Functions:
  - Dynamic requests: 60ms latency (served from Tokyo edge)
  - $0.0085/GB CloudFront pricing (Tokyo edge)
  - Total for 1TB Tokyo traffic: $8.70
  - Savings: $83.30/TB

CloudFront price classes to control cost:
  PriceClass_All:  All edge locations worldwide (most expensive)
  PriceClass_200:  US, Canada, Europe, Asia, Africa, Middle East
  PriceClass_100:  US, Canada, Europe only (cheapest)

For most SaaS apps: PriceClass_200 covers 95% of users at lower cost than PriceClass_All.
For US/EU focused apps: PriceClass_100 reduces CloudFront costs 30-40%.

Strategy 6: Multi-Cloud Egress Arbitrage

Cloudflare R2 — zero egress fees
  S3-compatible object storage
  Price: $0.015/GB storage (vs $0.023 for S3)
  Egress: FREE (to internet)
  
  Use case: Store assets, videos, user uploads in R2
  Serve directly from R2 or via Cloudflare CDN
  
  Migration from S3:
  aws s3 sync s3://my-bucket r2://my-bucket --endpoint-url https://account.r2.cloudflarestorage.com
  
  Savings example: 1PB/month egress
  AWS S3: $92,000/month egress
  Cloudflare R2: $0 egress
  Storage: $15,000 (R2) vs $23,000 (S3)
  Total savings: $100,000/month!

Backblaze B2 — $0.01/GB egress (90% cheaper than AWS)
  But: no free Cloudflare CDN integration (Cloudflare is a B2 partner — CDN is free)
  Use for: backups, cold storage, media delivery

DigitalOcean Spaces:
  $0.01/GB egress, S3-compatible
  First 1TB free with paid plan
  Simpler than R2 setup

When to use multi-cloud for storage:
  - Public assets (images, videos, downloads) = R2 or Backblaze B2
  - Private data = keep in AWS for latency and security
  - Backups = cheapest option (Glacier Deep Archive or B2)

Strategy 7: Direct Connect for High-Volume Hybrid

AWS Direct Connect pricing:
  Port fee: $0.025-0.30/hr depending on capacity (1G or 10G)
  Data transfer via Direct Connect: $0.02/GB (vs $0.09/GB internet egress)
  
  For 100TB/month:
  Internet egress: $7,700
  Direct Connect (1G port): $18/day + $2,048 data = $2,066/month
  Savings: $5,634/month — pays for itself above ~50TB/month

  Use cases:
  - Hybrid cloud with significant on-premises ↔ cloud traffic
  - Financial services regulatory requirements
  - Consistent low-latency connections
  - Large data movement (backups, replication, batch ETL)

Egress Cost Calculator

def calculate_monthly_egress_cost(gb_per_month: float, provider: str = "aws") -> dict:
    """Calculate egress costs and show optimization potential."""
    
    costs = {
        "aws": [
            (100/1024, 0),          # First 100GB free
            (10 * 1024, 0.09),      # Next 10TB
            (50 * 1024, 0.085),     # Next 40TB
            (150 * 1024, 0.07),     # Next 100TB
            (float('inf'), 0.05),   # Over 150TB
        ],
        "gcp_standard": [
            (1 * 1024, 0.085),      # First 1TB
            (10 * 1024, 0.07),
            (float('inf'), 0.06),
        ],
        "azure": [
            (5 * 1024, 0.087),
            (30 * 1024, 0.083),
            (float('inf'), 0.07),
        ],
        "cloudfront": [
            (10 * 1024, 0.0085),    # First 10TB
            (50 * 1024, 0.008),
            (150 * 1024, 0.006),
            (float('inf'), 0.004),
        ]
    }
    
    def calc_cost(tiers, gb):
        total = 0
        remaining = gb
        prev = 0
        for limit, rate in tiers:
            if remaining <= 0:
                break
            tier_gb = min(remaining, limit - prev)
            total += tier_gb * rate
            remaining -= tier_gb
            prev = limit
        return total
    
    direct_cost = calc_cost(costs[provider], gb_per_month)
    cf_cost = calc_cost(costs["cloudfront"], gb_per_month) if provider == "aws" else 0
    
    return {
        "provider": provider,
        "monthly_gb": gb_per_month,
        "direct_egress_cost": round(direct_cost, 2),
        "cloudfront_cost": round(cf_cost, 2),
        "cloudfront_savings": round(direct_cost - cf_cost, 2),
        "r2_cost": 0,  # Cloudflare R2 = free egress
        "r2_savings": round(direct_cost, 2),
    }

# Example
print(calculate_monthly_egress_cost(100 * 1024))  # 100TB
# Output:
# direct_egress_cost: 7,700
# cloudfront_cost: 770
# cloudfront_savings: 6,930
# r2_savings: 7,700

Conclusion

Egress fees are a tax on your success — the more users you serve, the more you pay. But most of that cost is avoidable. CDNs reduce origin fetch by 90%+. VPC endpoints eliminate NAT Gateway processing. Cloudflare R2 eliminates storage egress entirely. Compression reduces payload sizes 60-80%.

For most applications, the combination of CloudFront for user-facing traffic + VPC endpoints for AWS service traffic + Cloudflare R2 for public static assets reduces total egress costs by 70-90%. At 100TB/month, that is $7,000/month in savings for a few hours of configuration work.

A

Alex Thompson

CEO & Cloud Architecture Expert at ZeonEdge with 15+ years building enterprise infrastructure.

Klaar om uw infrastructuur te transformeren?

Laten we bespreken hoe we u kunnen helpen vergelijkbare resultaten te bereiken.