$osscostcalc.comSelf-hosting cost intelligence

The Bandwidth Cost Traps Every Self-Hoster Hits Eventually

9 min read·1,720 words·Cost

TL;DR

Compute is cheap; moving bits off the box is what kills your budget. This guide breaks down the three bandwidth billing models used by Hetzner, DigitalOcean, and Linode, walks through three real workloads where egress dominates, and shows when a CDN actually pays for itself versus when it just adds a second invoice.

TL;DR

Your €4.50 Hetzner CX22 is not the line item that will hurt you. Egress is. Three providers, three completely different billing philosophies, and one universal pattern: people pick the cheapest VM, ignore the bandwidth column, and discover the truth on the second month's invoice. This guide unpacks how pooled, included, and metered bandwidth actually behave under load, then runs the math on video, file storage, and a busy WordPress install.

Why egress is the silent budget-killer

CPU and RAM are predictable. You provision a 2 vCPU / 4 GB box, and unless your code goes sideways, that number on the invoice never moves. Bandwidth is the opposite. It scales with your success: the more users you have, the bigger the bill, and there is no upper bound until you put a limiter in front of it. Worse, egress is often billed at a markup that has nothing to do with the underlying transit cost. AWS famously charges $0.09/GB for the first 10 TB out. Hetzner charges €1.00/TB beyond your included allowance. That is a 90x spread for moving the same bytes.

The three providers this site tracks each picked a different philosophy:

  • Hetzner: generous included allowance per VM (20 TB on most EU Cloud instances, 1 TB on US instances), then a hard but cheap overage rate of about €1.00/TB.
  • DigitalOcean: per-droplet allowance (500 GB to 10 TB depending on plan), with the clever twist that allowances are pooled across your account. Overages are $0.01/GB.
  • Linode (Akamai): per-instance allowance similar to DO (1 TB to several TB), also pooled at the account level. Overages historically $0.005/GB, though enforcement has been inconsistent.

Those three words — included, pooled, metered — are doing a lot of work, and the difference between them is where the traps live.

Pooled vs included vs metered, in plain English

Included (per-instance)

This is the Hetzner model. Each VM ships with a fixed allowance attached to it. A CX22 at €4.51/mo comes with 20 TB of EU egress. If you do not use it, you do not get to roll it over, and you cannot lend it to another VM. Burn through it and you pay the overage rate on that specific machine.

The win: the allowance is huge relative to the price. A €4.51 box that includes 20 TB of egress is effectively unmetered for almost every hobby workload. The trap: if you run ten small VMs and one of them is your busy app, you cannot pool the other nine allowances to help.

Pooled (account-wide)

DigitalOcean and Linode both pool. A basic $6 droplet has 500 GB of included transfer; ten of them gives you 5 TB of shared pool. The marketing copy makes this sound like a generous flex, and for fleets it genuinely is. The trap is psychological: people see "pooled" and assume "unlimited." It is not. Once the pool is drained, every additional GB is billed at the overage rate, and that rate is roughly 10x what Hetzner charges (about $10/TB vs €1/TB).

Metered (pay-as-you-go from byte zero)

This is the hyperscaler model — AWS, GCP, Azure — and it is what self-hosters are usually trying to escape. None of the three providers on this site bill this way for their standard VMs, but their object storage products often do. DigitalOcean Spaces, for example, includes 1 TB of outbound transfer with the $5/mo base fee, then $0.01/GB after. Hetzner Object Storage is similar in spirit but cheaper.

The point of laying these three models side-by-side: when you compare a $6 DO droplet to a €4.51 Hetzner CX22, you are not comparing 500 GB of bandwidth to 20 TB. You are comparing two completely different risk profiles. The Hetzner number is the budget. The DO number is a deductible.

Scenario 1: a small video hosting side project

You self-host PeerTube or Owncast for a few hundred regular viewers. A single 1080p stream at 5 Mbps is roughly 2.25 GB/hour. Assume 300 hours of total viewing per month across all users — modest for a niche channel.

That is about 675 GB of egress before you account for thumbnails, previews, web UI, or RSS pulls. Round up to 800 GB.

Provider Plan Monthly cost Bandwidth used vs included Overage
Hetzner CX22 (EU) €4.51 800 GB / 20 TB €0
Hetzner CPX11 (US) $5.18 800 GB / 1 TB $0
DigitalOcean Basic $6 droplet $6.00 800 GB / 500 GB $3.00
Linode Nanode 1 GB $5.00 800 GB / 1 TB $0

Now double the audience. 1.6 TB of egress.

Provider Plan Monthly cost Overage Total
Hetzner CX22 (EU) €4.51 €0 €4.51
DigitalOcean $6 droplet $6.00 $11.00 $17.00
Linode Nanode 1 GB $5.00 $3.00 $8.00

The Hetzner box is now four times cheaper than DO for the same workload, and the gap widens linearly with every additional viewer. Video is the canonical case where Hetzner's included allowance is the right answer, full stop — assuming your audience can tolerate EU latency or you are willing to run a US instance with the smaller US allowance.

Scenario 2: photo and file storage with public sharing

You run a Nextcloud or Immich instance with 200 GB of photos, and you share albums occasionally. Most months you push 100 GB of egress. Twice a year you share a wedding album and burn 2 TB in a weekend.

Steady-state, every provider is fine. The interesting question is the spike.

  • Hetzner: 2 TB on a CX22 is still inside the 20 TB allowance. The wedding costs you nothing.
  • DigitalOcean: a $12 droplet (1 TB included). The 2 TB spike eats your full allowance plus 1 TB of overage = $10. Total month: $22 instead of $12.
  • Linode: a $12 Linode includes around 2 TB. You squeak by, but if the album goes mildly viral you are paying $0.005/GB after.

This is where the "pooled" framing actually matters. If you run five $12 droplets on DO, you have 5 TB of pooled allowance, and the 2 TB spike on one of them is absorbed silently by the unused capacity on the others. Solo operators with a single VM never see this benefit.

The object storage detour

A tempting answer is to push static media to Spaces, Hetzner Object Storage, or Linode Object Storage. Pricing for the three lands in a similar range: $5–6/month for ~250 GB of capacity plus ~1 TB of included egress, with overages around $0.005–0.01/GB. Hetzner's offering is the cheapest per TB of egress overage in this category.

The trap: object storage egress is separate from your VM's pooled allowance on DO and Linode. Moving your photos to Spaces does not free up bandwidth on your droplet — it just splits the bill into two columns. Sometimes that is a win (cheaper per GB at scale), sometimes it is just billing complexity.

Scenario 3: a busy WordPress site

A WordPress install with caching, getting 500k pageviews per month. Average page weight with images: 800 KB. That is 400 GB of egress at the absolute minimum, before you count RSS, REST API hits, wp-admin, and bots — which often double the real number to 800 GB to 1 TB.

This is squarely in the "every provider works, but the overage risk is asymmetric" zone. The interesting cost is not the steady state — it is what happens when a post hits the front page of Hacker News and you serve 2 million pageviews in 48 hours.

A viral spike of 2M pageviews at 800 KB is 1.6 TB on top of your normal traffic. On a $12 DO droplet, that is roughly $6 of overage — annoying but survivable. On a $6 droplet, it is more like $11. On a CX22, it is rounding error.

The bigger problem in this scenario is usually not bandwidth cost. It is the VM falling over under the request volume well before bandwidth becomes the binding constraint. Which leads directly to CDN math.

The CDN offloading math

A CDN in front of your origin does two useful things: it absorbs traffic spikes (capacity), and it serves bytes cheaper than your VM provider does (cost). The second part is where people get the math wrong.

Cloudflare's free tier serves unmetered cached bandwidth. For static-heavy sites, this is a no-brainer — you are trading zero dollars for potentially hundreds of dollars of avoided egress. Bunny.net charges roughly $0.01/GB in EU/NA. Fastly and CloudFront are 3–8x more.

The break-even calculation is simple. If your origin egress costs $0.01/GB (DO overage) and Bunny costs $0.01/GB, the CDN only saves you money if its cache hit ratio is high enough that you are not paying twice (origin → CDN → user). For mostly-static sites, hit ratios of 90%+ are normal, so the effective cost is closer to $0.001/GB origin + $0.01/GB CDN = $0.011/GB. Slightly worse than direct, but you get DDoS absorption and lower latency.

Now run the same math against Hetzner. Origin egress is effectively free up to 20 TB. Adding Bunny means you are paying $0.01/GB on traffic that previously cost zero. For a pure cost play, the CDN makes Hetzner more expensive, not less. You add a CDN to a Hetzner box for latency, resilience, or to protect against DDoS — not to save money on bytes.

Cloudflare free is the exception that breaks the rule. If your content is cacheable and you do not need fancy edge logic, putting Cloudflare in front of a Hetzner origin gives you global PoPs at zero marginal cost, while preserving your 20 TB allowance as a safety net for cache misses.

Quick reference: when each model wins

Workload shape Best fit Why
Predictable, high egress (video, downloads) Hetzner included Cheapest per TB at any scale
Bursty, low average (file sharing, blogs) DO/Linode pooled (multi-VM) Pooling absorbs spikes
Single VM, low traffic Any — pick on other criteria Bandwidth is not the binding cost
Global audience, latency-sensitive Any + Cloudflare free CDN solves latency; egress model becomes secondary
Mixed static + dynamic at scale Hetzner origin + Cloudflare Free CDN, generous origin allowance

Decision checklist for this week

  1. Measure your actual egress. vnstat, nethogs, or your provider's dashboard. Guessing is how people end up surprised.
  2. Project the next 12 months at 2x current traffic. If that number exceeds your included or pooled allowance, the cheap-VM math no longer applies — re-run the comparison on the osscostcalc calculator with realistic egress.
  3. Identify your top three URLs by bytes served. If they are static (images, video, downloads), they belong behind a CDN or in object storage, not on your VM.
  4. Put Cloudflare free in front of anything public. It costs nothing, it preserves your origin allowance for cache misses, and it makes the next viral spike a non-event.
  5. Set a billing alert. Every provider supports them. The €5 box that turned into a $200 invoice is always a story about someone who did not set the alert.

The headline VM price is a marketing number. The bandwidth column is the real one. Read it before you migrate, not after.

bandwidthegresscdnhetznerdigitaloceanlinode