On February 6, 2026, Salesforce moved Heroku into sustaining engineering mode: no new features, no new Enterprise contracts, maintenance and security patches only. Within weeks, the migration guides arrived — and nearly all of them priced the same thing: the dynos. Two Standard-1X dynos at $25 each, roughly $50 a month, versus whatever Render, Railway, or Fly.io charges for equivalent compute. Railway's widely shared 2026 backend roundup even spelled out the genre's blind spot in passing: Postgres, Redis, and Kafka add-ons "still available and still good," so if your app works, there's no urgent reason to move.
That advice is half right. The add-ons still work. But "still good" describes today, and sustaining mode is a statement about every tomorrow after it. Nobody priced what a frozen platform means for the stateful layer a team bolted on over a decade — and for a typical Heroku app, that layer costs as much as the dynos it runs on:
| Layer | Typical pick | List price |
|---|---|---|
| Web dyno | Standard-1X | $25/mo |
| Worker dyno | Standard-1X | $25/mo |
| Postgres | Standard-0 (no HA) | $50/mo |
| Redis | Mini–Premium-0 | $3–30/mo |
| Kafka | Entry tier | $100+/mo |
The compute half of that table is $50. The data half starts at $53 and climbs past $150 the moment event streaming enters the picture. Every comparison that prices the dynos and waves at "add-ons at ~$15–30" has the migration backwards. Stateless compute is fungible — a Rails or Django app that runs on a dyno runs on any PaaS with a buildpack. A decade of Postgres rows, a Redis dataset with persistence semantics your code depends on, and Kafka topics with consumer offsets are not fungible. If you're planning a Heroku exit, migrate the stateful layer first and the dynos last. Here's what sustaining mode concretely means for each data service, and the order to move them in.
What "sustaining" actually freezes in each data service
Sustaining mode is not a shutdown — The Register's February coverage stressed there is no death date, and existing customers can keep renewing. It is a feature freeze with layoffs behind it (roughly a thousand people across Heroku and Agentforce, per February reporting). For stateless compute that freeze is mostly invisible: your dyno runs the same slug the same way. For managed data services, a freeze compounds, because databases live on a treadmill of major versions, extensions, and engine features that a frozen team stops tracking.
Postgres: the treadmill is already moving under you. Heroku supports each Postgres major for three years, versus five from the PostgreSQL project itself. New databases provision on the current default (17, with 18.3 observed for new installs in late 2026), and Heroku notifies tenants when their major approaches end-of-life — PostgreSQL 15 reaches Heroku EOL with a forced upgrade to PG 18 by December 20, 2026, after which Heroku reserves the right to force-upgrade or even deprovision stragglers. The upgrade path (pg:upgrade:dryrun, pg:upgrade:prepare, pg:upgrade:wait) is documented and real, but every method requires application downtime.
Under a living platform, that cadence was an annoyance. Under sustaining mode, it's a ratchet: the forced upgrades keep coming because EOL dates are contractual, while the things that would make them painless — faster major-upgrade paths, new plan shapes, new extension support — do not. The extension list is effectively frozen where it stands: pgvector is available on production-tier PG 15 databases today, but if your roadmap wants the next Postgres extension the ecosystem produces, a sustaining-mode platform is the wrong place to wait for it.
Redis: tiers frozen at 2026 shapes. Heroku Data for Redis spans Mini ($3/mo) through Premium tiers ($30 and up) with the persistence, failover, and eviction semantics each tier shipped with. A feature freeze here means no new engine-major tracking, no new tier shapes for workloads that outgrow the current ladder, and failover behavior pinned to whatever it is today. For a cache you can re-seed, that's tolerable. For Redis used as a primary store — sessions, rate-limit counters, job queues with persistence on — it's the same ratchet as Postgres in miniature: the workload grows, the platform doesn't.
Kafka: the most expensive thing to leave on a frozen platform. Apache Kafka on Heroku starts around $100 a month for multi-tenant entry tiers, with dedicated clusters far above that. Broker-version tracking, new topic/retention features, and connector ecosystem work all stop being things the platform invests in. Kafka tenants also tend to be the stickiest: consumer offsets, topic configs, retention policies, and schema assumptions accumulate in ways a pg_dump equivalent can't capture in one command.
The marketplace behind all three. Heroku Elements lists 150–200+ third-party add-ons — monitoring, search, queues, data pipelines — provisioned with one command on one bill. That one-bill integration was Heroku's genuine moat. But third-party providers build and maintain integrations where platforms are growing. Against a frozen platform API and a customer base that can only shrink, the rational provider decision is maintenance-only on the Heroku integration too — which means the long tail of add-ons your app depends on quietly enters its own sustaining mode, without anyone announcing it.
Migrate state first: the exit order
The standard Heroku exit plan starts with "which PaaS runs my web dynos" and treats data as a migration detail. Invert it. The correct order is:
- Postgres first. It's the largest dataset, the longest migration, and the only layer where a mistake loses data customers can't regenerate. Everything else schedules around it.
- Redis second — but only after deciding whether it needs migrating at all (more below).
- Kafka third, because consumer offsets and topic history force a coordinated cutover with whatever replaces the consumers.
- Dynos last. Repoint
DATABASE_URL,REDIS_URL, andKAFKA_URLat their new homes, deploy the same slug elsewhere, and shut the dynos down. If the data migration is done, the compute migration is a deploy.
This ordering has a second virtue: each step de-risks the next. Once Postgres lives somewhere new, the app can run on Heroku dynos against an external database indefinitely — Render's own Heroku-migration docs assume exactly this intermediate state. You get to validate the new data home under production load while the old compute still works, instead of cutover day moving everything at once. Sustaining mode has no death date, so this is a plan-on-your-schedule migration, not a fire drill. Use the lack of urgency; don't let it become complacency about the forced-upgrade ratchet above.
Postgres mechanics, by database size
The community consensus — "migrate databases first; pg_dump/pg_restore for small ones, logical replication for zero-downtime" — is right but underspecified. What you actually run depends on how much data you have:
Under ~2 GB: dump and restore in one pipe. This covers most apps that grew on Hobby or Essential plans. One compressed custom-format dump, ownership and ACLs stripped (Heroku roles don't exist on the other side), straight into the new database:
pg_dump -Fc --no-acl --no-owner -d "$HEROKU_DB_URL" \
| pg_restore --clean --no-acl --no-owner -j 4 -d "$NEW_DB_URL"Expect minutes of downtime in a maintenance window: put the Heroku app in maintenance mode, dump, restore, verify row counts, repoint DATABASE_URL. Render's migration skill uses render psql for this tier without even needing an external connection string.
2–50 GB: staged dump, parallel restore, verified. Same pipeline, but write the dump to disk first so a failed restore doesn't require re-dumping from Heroku, use parallel restore jobs (-j 4 or higher), and budget the window honestly: tens of gigabytes restore at single-digit GB/minute rates depending on index weight. Verify schema object counts and per-table row counts against the source before cutover — don't trust a clean exit code alone.
Over ~20 GB or under heavy write load: logical backup, then cutover. Heroku documents a dedicated logical-backup path for large databases (their pg:backups flow plus pg:backups:download), and Render's docs explicitly route databases over 20 GB through it before the same pg_restore import. For genuinely zero-downtime requirements at this size, set up logical replication from Heroku Postgres to the new primary first, let it catch up, then cut over writes. It's the only option that avoids a maintenance window measured in hours — and it's also the only option with real operational surface (slot monitoring, schema-change discipline during catch-up), so reserve it for databases whose downtime cost justifies it.
One trap spans all tiers: extensions and versions must exist on both sides. If the source uses an extension the destination doesn't offer, the restore fails at CREATE EXTENSION — audit pg_extension before migration day. And match major versions: restoring a PG 15 dump into a PG 17 database usually works, but collation and behavior deltas make same-version restores the safe default. Given Heroku's December 2026 forced PG 15→18 upgrade, a team migrating this fall should decide once whether to upgrade-then-migrate or migrate-then-upgrade, not discover the question mid-cutover.
Redis and Kafka are not just smaller Postgreses
Redis: usually, don't migrate it — re-seed it. Render's migration guidance says this outright: Key Value / Redis is usually ephemeral cache, so skip the data and point the new instance at an empty store. Warm the cache before cutover (run the new Redis alongside the old one and let reads populate it, or replay your warm-up job), then flip REDIS_URL. Only migrate bytes when Redis holds something irreplaceable: persistent sessions, Sidekiq/Resque queues with at-least-once semantics your business depends on, rate-limit state. In that case redis-cli --rdb dump-and-restore or a replica-of migration works — but first ask whether that dataset should have been in Postgres all along. The Heroku exit is the cheapest moment you'll ever get to fix that mistake.
Kafka: migrate the offsets, not just the topics. Recreating topics on the new cluster is the easy part; the state that matters is consumer-group offsets and retention history. The safe cutover is dual-run: stand up the new cluster, mirror topics (MirrorMaker 2 or the destination's import tooling), move consumers one group at a time while watching lag, and only retire the Heroku cluster when every group's committed offsets live on the new side. Teams that treat Kafka like "Postgres with topics" and try a stop-the-world copy learn the difference the hard way — there is no pg_dump for "where 40 consumer groups were in their partitions."
Where the data lands
The destination decision is downstream of the migration mechanics, not upstream of them — but the 2026 menu is short:
- Render is the closest structural match: managed Postgres from $6 a month with point-in-time recovery on paid instances, automated backups, and read replicas on larger tiers, plus managed Key Value (Redis) from $10 a month. A
Procfileplus Heroku add-ons maps almost one-to-one onto Render services. If you want the Heroku shape with a living roadmap, this is the default answer — our 2026 PaaS pricing ledger puts Render and Heroku on the same workload so you can see the dollar delta. - Railway prices Postgres and Redis as usage-metered services ($5 Hobby / $20 Pro platform fee, then roughly $20/vCPU and $10/GB-RAM monthly). It fits spiky workloads and teams that already think in usage terms, but the bill needs modeling — a steady-state production database can cost more metered than on a fixed plan.
- Machines you own are the third option and the one sustaining mode argues for most strongly. A Postgres you run on your own hardware has no platform EOL distinct from the PostgreSQL project's five-year window, no frozen extension list, and no marketplace dependency for backups. The price is operational: you own failover, PITR, and major upgrades. That trade only makes sense with automation doing the owning — declarative machine lifecycle, health-checked failover — not a pet VPS with a cron job.
Whichever you pick, keep the intermediate state as long as it's useful: Heroku dynos talking to an external Postgres is a supported, sane architecture during the migration, not a hack. The dynos are the last thing to move precisely because they're the easiest.
The window is open, not closing — yet
Sustaining mode's strangest property is that nothing is on fire. Apps run, add-ons bill, renewals process. The risk isn't a shutdown notice; it's the slow divergence between a frozen platform and a moving ecosystem — forced Postgres majors with no new upgrade tooling, an extension list that only ages, a marketplace whose providers invest elsewhere. That divergence is already priced into every serious 2026 comparison of Heroku alternatives. What's missing from those comparisons is the plan above: inventory the add-on layer, move Postgres first with size-appropriate mechanics, re-seed Redis, dual-run Kafka, and shut the dynos off last.
Stateless compute was always the interchangeable part. It took Salesforce freezing the platform to make that obvious. Migrate the decade of state first — the dynos will take an afternoon.
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.



