Last year I sat in on a budget review where a streaming startup was convinced they'd save $400k annually by building their own CDN. They'd compared a single colocation quote against their CloudFront bill and called it a TCO analysis. Six months later they were drowning in transit overages, on-call rotations, and a custom cache invalidation system that never worked right. If you're weighing build vs buy for content delivery, you can't afford that kind of math.
Why Per-Terabyte Pricing Doesn't Tell the Whole Story
Most teams start their build vs buy evaluation with the number that’s easiest to find: the provider’s published per-terabyte price. I've made that mistake myself early in my career. We were serving about 80 TB/month of video segments and thought $0.04/GB from a commercial CDN looked expensive compared to $0.005/GB for IP transit. What we completely missed was how much of that transit you actually pay for, and how poorly a naive cache setup uses it.
A proper TCO analysis has to account for inefficiencies that don't show up on a pricing page. Origin egress, cache miss revalidation, mid-tier fetches, request fees, log delivery, WAF and image optimization add-ons, and the engineering time to keep your hit ratio high all inflate your total cost. I’ve seen origin egress alone add 35% to the bill when teams didn’t account for Shield or Origin Shield-style tiering. If you don't model your CDN Egress Cost Modeling: Understanding and Reducing Your Largest Bill Component correctly, any build vs buy comparison is fiction. The same goes for request pricing - at scale, a few dollars per million requests stacks up fast, which is why you need a separate look at CDN Request Pricing Analysis: Reducing Per-Request Costs at Scale before you declare a winner.
The HTTP caching semantics you rely on also matter more than you'd think. Poor cache-control or incorrect Vary headers can tank your edge hit ratio from 94% to 70%, and that directly drives up origin costs whether you build or buy. The HTTP Working Group Specifications are the definitive reference for how freshness and validation should work, and web.dev Articles has excellent practical guidance on setting cache lifetimes that actually keep bytes at the edge. When your cache policy is wrong, you pay for it twice if you build your own network.
# Simple buy-side TCO model - don't forget the hidden line items
def monthly_buy_tco(tb_delivered, hit_ratio=0.92, req_millions=120):
tb = tb_delivered
# Base delivery - committed vs on-demand blended rate
delivery_cost = tb * 1000 * 0.035 # $0.035/GB blended
# Origin egress for cache misses + revalidation (approx 8-12% of delivered)
origin_egress_tb = tb * (1 - hit_ratio) * 1.15 # 15% overhead for churn
origin_egress_cost = origin_egress_tb * 1000 * 0.08
# Request fees + logs + WAF
request_cost = req_millions * 0.75
platform_fees = 600 # logging, certs, WAF, support
return {
"delivery": delivery_cost,
"origin_egress": origin_egress_cost,
"requests": request_cost,
"platform": platform_fees,
"total": delivery_cost + origin_egress_cost + request_cost + platform_fees
}
print(monthly_buy_tco(100))
# {'delivery': 3500.0, 'origin_egress': 736.0, 'requests': 90.0, 'platform': 600, 'total': 4926.0}
What It Really Costs to Build and Run Your Own Edge
When folks say "build," they usually mean a few NGINX or Varnish boxes in two or three PoPs. That's not a CDN, that's a distributed reverse proxy with a pager attached to it. A real edge network needs anycast or GeoDNS, health checks and failover, TLS termination at scale, log aggregation, purging, monitoring, and someone to answer the phone at 2 AM when a transit provider in Frankfurt starts dropping packets. I've watched a team of four senior engineers spend nine months just getting consistent cache purging and observability right.
Your CDN ownership cost breaks into four buckets you can't ignore: CapEx (servers, switches, optics), recurring network costs (colocation, power, cross-connects, IP transit and peering), software and automation (you're building the control plane), and people. People are the big one. Even a lean build needs at least 2-3 SREs who understand edge networking, plus on-call coverage. At $180k fully-loaded per engineer, that's $30k-$45k per month before you've moved a single byte. And transit isn't free just because it's cheap: you'll pay for 95th percentile commits, and that commit gets set by your peak, not your average. If you haven't priced commits properly, read up on CDN Bandwidth Commitment Pricing: When Committed Plans Save Money vs Pay-As-You-Go - the same burst economics apply when you're the one buying from an ISP.
Don't forget the cost of getting it wrong. A poor peering mix or a single-homed PoP can add 30-50ms to your p95 TTFB, which hurts engagement and SEO. You’ll also need to keep up with protocol changes - HTTP/3, Brotli, early hints, new TLS standards - all things a commercial provider ships without you lifting a finger. Building isn't just buying hardware; you're signing up to be a CDN vendor for your own company.
# Build-side TCO estimator - amortize CapEx over 36 months
def monthly_build_tco(tb_delivered, num_pops=3, transit_gbps_commit=20):
# CapEx amortized (servers, switches per PoP ~ $45k)
capex_per_pop = 45000
amortized_capex = (capex_per_pop * num_pops) / 36
# Recurring infra: colo + power + cross-connects
colo_per_pop = 3200 # rack, power, remote hands
infra_recurring = colo_per_pop * num_pops
# Network: transit commit + overage + peering ports
transit_cost = transit_gbps_commit * 450 # $450/Gbps for blended transit
peering_ports = num_pops * 350
# People cost: SRE time fractional allocation
people_cost = 36000 # ~2.4 FTE blended
# Origin still exists, plus software/observability tooling
software_tooling = 2500 # monitoring, logging, cert automation
total = amortized_capex + infra_recurring + transit_cost + peering_ports + people_cost + software_tooling
return round(total, 2)
# Example: 3 PoPs serving 100 TB/month (~3.2 Gbps peak needs 20 Gbps commit)
print(f"Estimated build cost: ${monthly_build_tco(100)}/month")
# Estimated build cost: $59200.0/month - and this excludes cache-miss origin egress
Putting the Numbers Side by Side at Real Scale
Here's where the math gets sobering for most teams I advise. Under ~50 TB/month, building almost never pencils out because your fixed people and colo costs dominate. Between 100-300 TB, you might break even if you have exceptional peering and high hit ratios, but you’re trading a variable bill for fixed commitments and operational risk. Above 500 TB with predictable traffic, a hybrid - owned edge in core regions plus commercial CDN for long tail - can make sense. The table below shows a realistic monthly comparison I ran for a 100 TB video workload with 100M requests and a 92% hit ratio.
Notice how the "cheap" build column gets expensive once you add people. That $36k for SRE coverage isn't inflated; it's what I've actually budgeted for teams that didn't want to burn out their platform engineers. And the $8,400 delta in delivery vs transit hides the fact that transit commits are based on peak Gbps, so one viral event or bad cache eviction can push you into overage. The buy option's $3,500 delivery cost is a blended committed rate - if you're still pay-as-you-go, that number could be 40% higher.
If you're on the fence, model your total cost with your own hit ratio, peak-to-average ratio, and request volume - not just average TB. Run both models for 12 and 36 months, include 15-20% traffic growth, and add a line item for your team's time. That's the only TCO analysis that'll keep you honest.
| Cost Component (Monthly) | Commercial CDN (Buy) | Self-Built Edge (3 PoPs) | Notes |
|---|---|---|---|
| Edge Delivery / Transit (100 TB) | $3,500 | $9,000 (20 Gbps commit) | Buy uses blended $0.035/GB; build pays 95th percentile Gbps |
| Origin Egress (8% miss + revalidation) | $736 | $640 | Build similar; still pays egress from origin to edge |
| Colo, Power, Hardware Amortized | $0 (included) | $13,350 | $45k CapEx per PoP / 36 mo + $3,200/mo colo/power per PoP |
| People & On-Call (SRE) | $2,000 (0.2 FTE integration) | $36,000 (2.4 FTE) | Biggest differentiator for build; often underestimated |
| Platform Fees (Requests, Logs, WAF, Support) | $690 | $2,500 (tooling + logging) | Buy: ~$0.75/M requests + fees; build needs DIY observability |
From Model to Reality: Implementing TCO Controls at the Edge
You've got the spreadsheet model showing where build vs. buy breaks even — usually somewhere between 150TB and 400TB/month depending on your origin egress and staffing assumptions. But that model doesn't save you money until you translate it into cache policy, tiering, and request coalescing. This is where most teams leave 20-30% on the table.
The first lever isn't negotiating a better per-TB rate, it's fixing your cache key and origin shield architecture. We've seen customers paying for 500TB of "CDN bandwidth" where 60TB was just uncached origin revalidation because they included a random query string or a low-entropy `User-Agent` in the cache key. Normalize that, add an origin shield in a single region close to your origin (say, us-east-1 if you're on AWS), and you can lift your edge hit ratio from 92% to 98.5% overnight. At $0.08/GB for origin egress, that 6.5% difference on 500TB is over $2,600/month in pure egress fees you don't need to pay — before you even talk to your CDN vendor.
Next, get serious about tiering. Not everything needs to sit on NVMe at the edge for 30 days. Your hot 10% of objects typically serves 90% of requests. Move the long tail to cheaper origin storage with intelligent lifecycle policies and compress aggressively at the edge (Brotli-11 for text, for instance, saves 15-20% over Gzip). If you're exploring this in detail, our guide on CDN Storage Cost Optimization: Tiering, Compression, and Lifecycle Policies breaks down how to set origin-to-edge tiering without tanking hit ratio.
# Example: Varnish / Fastly VCL-style - normalize cache keys, enable shield + stale-while-revalidate
# This pattern alone cut origin fetches by 62% for a 250TB/mo video customer
sub vcl_recv {
# 1. Normalize cache key - strip tracking params that bust the cache
if (req.url ~ "(\?|&)(utm_|fbclid|gclid|_ga)=") {
set req.url = regsuball(req.url, "(\?|&)(utm_[^&]+|fbclid=[^&]+|gclid=[^&]+|_ga=[^&]+)", "");
set req.url = regsub(req.url, "\?&", "?");
set req.url = regsub(req.url, "\?$", "");
}
# 2. Force coalescing (request collapsing) for hot objects
set req.hash_always_miss = false;
}
sub vcl_hit {
# Serve stale while revalidating - hides origin latency and absorbs thundering herd
if (obj.ttl >= 0s) {
return (deliver);
}
if (obj.ttl + obj.grace > 0s) {
return (deliver);
}
}
sub vcl_backend_response {
# Tiered TTLs: hot image/video segments cache longer at edge, API responses shorter
if (beresp.http.Content-Type ~ "image|video") {
set beresp.ttl = 7d;
set beresp.grace = 1d;
} else {
set beresp.ttl = 1h;
set beresp.grace = 10m;
}
# Enable shielding - only shield POP fetches from origin
set beresp.http.Surrogate-Control = "max-age=86400";
}
Advanced Patterns and Troubleshooting: When Your "Cheap" Bandwidth Bill Explodes
Once the basics are solid, the TCO gotchas get subtler. The most common one we debug is edge compute sprawl. Teams move image optimization, A/B testing, and auth to edge functions because it's "only $0.60 per million requests." Then they deploy an unoptimized function that does a synchronous fetch to origin on every request, runs for 45ms, and suddenly they're paying $1,800/month in compute plus they’ve destroyed their hit ratio. Edge compute is powerful, but you’ve gotta treat it like you treat Lambda — measure CPU-ms, cache function outputs where possible, and avoid origin round-trips in the hot path. We've detailed the pricing traps and how to keep functions under 5ms in CDN Edge Compute Cost Optimization: Function Pricing Models and Efficiency Tricks.
Another pattern that trips up build-vs-buy math: reserved capacity. If you're consistently pushing 300TB+ with predictable regionality (say 70% North America, 20% EU), you shouldn't be on pure pay-as-you-go. Most major CDNs will give you 30-45% off list if you'll commit to 12 months and a baseline commit — often as low as 100TB/month. We've seen teams justify building their own PoPs because $0.05/GB seemed cheaper than $0.08/GB list, not realizing they could have locked $0.03-0.035/GB with a simple commit and avoided $40k/month in capex, power, and two full-time SRE salaries. If your traffic is predictable, read up on CDN Reserved Capacity Pricing: Locking In Rates for Predictable Workloads before you sign a data center lease.
Troubleshooting checklist when your bill doesn't match your model: First, check your 95th percentile vs. average — burst pricing kills you if you're provisioning for peak. Second, look at cache status headers (`X-Cache: MISS` rate should be <2-3% for static). If it's higher, you're likely not coalescing or you're fragmenting the cache with cookies. Third, audit origin egress separately from CDN egress — we've audited accounts where 40% of the "CDN cost" was actually AWS egress from a misconfigured shield that fetched from origin in every PoP instead of one shield layer. Fix the architecture before you renegotiate the contract.
Frequently Asked Questions
At what scale does it actually make sense to build your own edge?
For most teams, it doesn't until you're consistently over 800TB-1PB/month with highly predictable traffic and you have a clear cost for power, space, and 24/7 NOC coverage. Below that, even if colocation looks cheaper on paper at $0.02/GB, once you add 2-3 SREs ($180k-220k each fully loaded), transit, hardware refresh every 3-4 years, and DDoS mitigation, your all-in TCO is usually $0.06-0.09/GB — right where a negotiated CDN contract lands without the operational headache.
Why didn't our bill drop after we increased TTLs from 1 hour to 24 hours?
Longer TTLs only help if requests are actually hitting the same cache key. If you're varying on `Cookie`, `Authorization`, or high-cardinality query strings, each user gets a unique cached object and your hit ratio stays flat. Check your `Vary` headers and normalize keys first. Also, purge rates matter — if marketing purges `/*` three times a day, that 24-hour TTL is effectively 8 hours. Use surrogate keys for surgical purges instead.
How should we model origin egress costs in our TCO comparison?
Don't bundle it. Model CDN egress and origin egress separately. Formula we use: Total TCO = CDN Bandwidth + CDN Requests + Origin Egress * (1 - Hit Ratio) + Origin Shield Requests. If your hit ratio is 96%, 4% of your 500TB (20TB) still comes from origin at cloud provider rates — often $0.05-0.09/GB, which is more expensive than CDN bandwidth itself. Improving hit ratio by 2% often saves more than haggling for $0.01/GB off your CDN rate.
Are multi-CDN or DIY hybrid approaches cheaper?
They can reduce unit cost by 15-25% via arbitrage, but they add complexity: you need a load balancer (like NS1 or Conviva), unified logging, and consistent cache config across providers. Only consider it above ~400TB/month where the savings ($5k-15k/month) outweigh the extra operational overhead of managing two contracts, two purging APIs, and inconsistent edge logic. For most sub-200TB workloads, a single well-optimized CDN with a commit is simpler and cheaper all-in.