Skip to main content

From $87 in Heroku Dynos to $7 on Hetzner: a Real 2026 Migration Bill, Line by Line

11 min readDora NodaDora Noda
Share
On this page

Nobody migrates off Heroku because a single dyno is expensive. Twenty-five dollars for a managed container that deploys on git push, rolls back in one command, and never pages you at 3 AM is a bargain. Teams migrate because the bill is never one dyno. It is two web dynos plus a worker plus Postgres plus Redis, each priced like it is the only thing on the invoice — and then it repeats every month, forever, while the app itself would fit comfortably on a box the size of a lunch order.

So let us do the thing migration writeups usually skip: price one concrete, boring, typical stack on both sides, line by line, at September 2026 rate cards — and count the egress line honestly instead of assuming it. Here is the answer up front; every receipt follows below.

Heroku (before)Hetzner CX (after)
Reference stack: Node.js API + worker + Postgres + Redis$87/mo~$7/mo
Multiplier—~12x cheaper
Annualized$1,044/yr$84/yr ($960/yr saved)

Four disclosures ride along with that table, because a multiplier without them is marketing. First, this is a list-price recompute from public pricing pages (Heroku's pricing page and Dev Center plan specs; Hetzner's post-June-15-2026 EU catalog), not a scanned invoice — but every rate below is cited so you can redo it. Prices are normalized at EUR→USD ~1.08 (September 2026), excluding VAT. Second, the after side is a single node with no HA or failover, running Postgres and Redis co-located with the app, versus multi-AZ Standard dynos and managed data services — the "where Heroku still wins" section prices what closing that gap costs.

Third, backups, snapshots, and ops/on-call time are excluded from both sides, which flatters Hetzner more than Heroku (Heroku's ops cost is bundled into its prices; Hetzner's is your evenings). Fourth, the savings are compute plus database; the egress delta between these two vendors is $0 versus $0 all the way to 20 TB, and the egress section shows exactly where egress actually bites.


The Heroku bill, line by line: $87​

The reference stack is the smallest thing a real side-project SaaS actually runs in production: a Node.js API with two web dynos for rolling deploys, one worker dyno for background jobs, a small Postgres, and a small Redis for sessions and rate limits. No review apps, no Private Spaces, no Shield — plain Heroku, priced off the current rate card:

Line itemPlanPrice
2x web dynosStandard-1X at $25 (512 MB RAM each)$50/mo
1x worker dynoStandard-1X at $25$25/mo
PostgresEssential-1 (10 GB, non-HA tier)$9/mo
RedisKey-Value Store Mini (25 MB)$3/mo
EgressBundled with dynos — no per-GB meter$0
Total$87/mo

Two rows deserve commentary. Standard-1X at $25 with 512 MB is Heroku's entry-level production dyno (Eco at $5 sleeps and throttles; Basic at $7 is a single half-GB hobby box), and two of them is the minimum for zero-downtime deploys via preboot. Essential-1 at $9 is the honest small-prod database choice — but note what it is: the Essential tier tolerates hours of downtime a month with no failover, which is exactly why the growing-prod rung in the sensitivity ladder jumps to Standard-0 at $50 (64 GB, 4 GB RAM) when customer data is on the line.

And then there is the egress row, which is the most important $0 in this post. Heroku does not meter bandwidth. There is no per-GB egress charge on any dyno tier — third-party calculators list it flatly as "no charge for egress," and comparison tables put "included in dyno cost" where other vendors put a meter. This matters because the naive version of this article claims the multiplier "shows up in the egress line." It does not. Heroku's tax is collected entirely in compute and add-ons, and anyone telling you otherwise has not read the invoice.

The egress math still belongs in this post — but as the table below shows, it belongs as the story of where metered vendors punish you, not Heroku.

The Hetzner bill, line by line: ~$7​

The identical containers — same Node.js API, same worker, Postgres and Redis co-located — run on a single Hetzner Cloud CX23 (2 shared vCPU, 4 GB RAM, 40 GB SSD) under a Cluster-API-managed single-node Kubernetes setup:

Line itemDetailPrice
1x CX23 (EU)2 vCPU / 4 GB / 40 GB, post-June-2026 catalog€5.49–6.49/mo ($6–7)
Transfer20 TB included; ~€1/TB overage$0 at this stack's traffic
Backups/snapshotsExcluded (see disclosures)$0 (not $0 cost — $0 counted)
Ops/on-callExcluded (see disclosures)$0 (not $0 cost — $0 counted)
Total~$7/mo

The consolidation assumption, stated plainly so you can reject it: a lightly-loaded Node API plus a worker plus a few-GB Postgres fit in 2 vCPU and 4 GB with headroom, and this is the standard single-box shape every migration writeup converges on. The contention limit is equally plain: one noisy neighbor — a runaway worker, a Postgres vacuum storm, a traffic spike — and all three tiers degrade together, with no second node to fail over to.

If that sentence made you flinch, price the separated-DB alternative instead: a second CX23 holding Postgres and Redis costs €12/mo total ($13), both nodes still flat, and the multiplier settles at ~7x instead of ~12x. Still a rout; just an honest one.

One more pricing note, because Hetzner's 2026 catalog will confuse anyone working from an old bookmark: the box this post prices is the CX23, not the CX22. Hetzner raised cloud prices twice in 2026 — a broader adjustment of up to ~37% on April 1, then a second round effective June 15 that pushed dedicated-vCPU CPX/CCX lines up as much as ~113–176% while the cost-optimized CX/CAX lines rose a more modest ~30–38%, citing the DRAM and NVMe price shock. The same reshuffle renamed a generation (old CX22 → CX23), and the old name is now deprecated in the provisioning API. Anyone whose mental model still says "€4.49 Hetzner box" is quoting a pre-2026 catalog.

The honest framing cuts both ways: Hetzner narrowed its own discount this year and the multiplier below still starts at 7x.

Egress math: the 0−vs−0-vs-0 line, and where egress actually bites​

Here is the table the title promised, at three monthly egress levels for the same stack:

Monthly egressHerokuHetzner CX23 (EU)Metered-cloud context (illustrative only)
0.5 TB$0 (bundled)$0 (inside 20 TB)~$45 at $0.09/GB EC2-style rates
5 TB$0 (bundled)$0 (inside 20 TB)~$450
25 TB$0 (bundled)~€5 (5 TB over 20 TB at ~€1/TB)~$2,250

Read it carefully. Between the two vendors this post compares, egress changes nothing: Heroku bundles it, Hetzner includes 20 TB per server — roughly two orders of magnitude above what this stack serves — with overage at about a tenth of a cent per GB. The third column is illustrative context only, not part of the before/after: it shows what the same traffic costs on a hyperscaler meter, which is the actual place egress "shows up" — and the reason egress belongs in a migration post at all.

Teams that outgrow bundled bandwidth do not usually land on EC2 egress pricing; they land on it from somewhere metered (a functions bill, a CDN-less object store, Fly.io's $0.12/GB Africa/India tier), and the Hetzner column is what "never think about it again" costs. The migration lesson is not "Heroku's egress is expensive" — it is that Heroku already solved egress by bundling it, and Hetzner matches that property at one-twelfth the compute price.

Sensitivity: hobby to growing prod​

One workload is one data point, and multipliers computed at a single convenient scale are how cost posts lie. Here is the ladder, with the Hetzner size stated per rung:

StageHeroku configHeroku billHetzner configHetzner billMultiplier
Hobby1x Basic ($7) + Essential-0 ($5)$12/mo1x CX23~$7/mo~1.7x
Small prod (mainline)2x Std-1X + worker + Essential-1 + KV Mini$87/mo1x CX23~$7/mo~12x
Growing prod2x Std-2X ($100) + worker ($50) + Standard-0 ($50) + KV Mini ($3)$203/mo2x CX23, app + separate DB~$14/mo~15x

Three honest readings. First, at hobby scale the multiplier nearly vanishes (~1.7x): a $12 Heroku setup is fairly priced, and migrating to save $5/month is a hobby in itself — stay.

Second, the multiplier is driven by per-dyno granularity, not usage: doubling Heroku RAM from 512 MB to 1 GB doubles the dyno price ($25 → $50 each) whether the app uses the headroom or not, while the flat box absorbs the same growth for $0 until you buy a second node. Third, the growing-prod rung is deliberately priced with Standard-0 Postgres and a separated database node on both sides — like-for-like-ish on HA posture for the data layer — and the gap still widens to ~15x, because Heroku's step functions compound (bigger dynos × more dynos + bigger database) while Hetzner's stays linear in node count.

Where Heroku still wins (and what the migration really costs)​

If the post ended at the ladder, it would be an ad. So here is the counter-case the multiplier owes you: Heroku genuinely wins for any team that values zero ops over unit economics, and the price of the multiplier is paid in kinds of work the tables exclude.

What $87 (or $203) actually buys: multi-AZ dyno placement you never configure, managed Postgres with point-in-time recovery and one-command forks/followers, review apps per pull request with zero pipeline work, buildpacks that turn git push into a running service without a Dockerfile, and a compliance and SOC 2 surface you inherit instead of building. Reproducing even half of that on owned hardware means writing Dockerfiles, running pgBackRest or Postgres-operator backups to object storage and testing restores, wiring CI to build and push images, managing TLS and DNS, and owning the 3 AM page when the single Hetzner node does what single nodes do.

At contractor rates, one bad on-call month erases the $960 annual saving — which is why the hobby rung says stay, and why teams with no platform engineer should read the ~12x as "the discount for hiring ops," not free money.

The migration gotchas, concretely: buildpacks do not transfer — containerize the app first and run it locally. Postgres moves via pg_dump/pg_restore with a write-freeze window (or logical replication for near-zero downtime); extensions and collations must match the target version. Redis persistence (AOF/RDB) needs configuring on the new box — Heroku's managed restarts hid that from you. Scheduler jobs move to cron or a job runner. And Heroku's add-on ecosystem (logging, monitoring, error tracking drains) becomes a set of vendor accounts you now manage.

None of this is hard; all of it is real, and it is the actual line item the $87 was paying for.

The bottom line​

A typical small-production Heroku stack costs $87/month at September 2026 list prices; the same containers on a post-repricing Hetzner CX23 cost ~$7/month — a ~12x gap (~7x with a separated database node, ~1.7x at hobby scale, ~15x as the stack grows). Egress, contrary to the folk version of this story, is $0 on both sides to 20 TB; the multiplier lives entirely in per-dyno compute granularity and managed-database tiers.

Hetzner's two 2026 price hikes narrowed the gap without closing it, and Heroku's bundled bandwidth plus zero-ops posture remain genuinely worth the premium for teams without platform capacity.

If that last sentence describes your team but the ladder still stings, the middle path is a self-hosted PaaS that keeps the git push workflow while billing you for flat hardware instead of per-dyno meters: declarative app resources on a Cluster-API fleet you own, with Postgres you control and bandwidth nobody meters.

Bex.co is the open-source, AI-native Render alternative — push a git repo, get a running HTTPS service on machines you own. Star the repo on GitHub or deploy your first app today.

Related articles

Check your move before you migrate

Free browser tools: check a render.yaml or your Render scripts against bex, or turn a Heroku app or docker-compose.yml into a draft render.yaml. Nothing you paste leaves your browser.

Open the migration tools