Independent marketplace for cloud provider accounts across 22 providers

Cloud Migration

Migrating Off Heroku: Options and Trade-Offs

Leaving Heroku means rebuilding the routing, builds, process supervision, configuration and logging the platform handled for you. This guide lists that scope, compares destinations and covers the database move and cutover.

Heroku dynos and add-ons mapped onto containers, load balancers and managed services

Why teams start looking

Heroku earns its keep by removing work. You push a git branch, a buildpack detects the language, and a running process appears behind TLS with logs attached. For a small team, that is a genuine amount of engineering you did not have to do.

Teams usually start looking elsewhere for one of three reasons. Cost per unit of compute grows uncomfortable as the application scales. A requirement appears that the platform cannot satisfy, such as a private network boundary, a specific compliance posture or a long-running process. Or the add-on ecosystem becomes the constraint rather than the convenience.

None of those are reasons to move in a hurry. The most expensive migrations off a platform like this are the ones that begin as a cost exercise and finish by rebuilding, badly, the operational features the platform provided for free.

Everything the platform quietly does for you

Write this list before evaluating destinations, because it is the real scope of the project.

  • Routing and TLS. The platform terminates HTTPS, manages certificates and routes to your processes. You will need a load balancer and a certificate renewal mechanism.
  • Build pipeline. Buildpacks turn a repository into a runnable slug. Elsewhere, that is a container build and a registry.
  • Process management. The Procfile declares web and worker processes, and the platform restarts them. You need a supervisor, an orchestrator or a systemd unit.
  • Configuration. Config vars are injected as environment variables. You need a secrets store and a way to deliver values to processes.
  • The managed database. Heroku Postgres includes backups, point-in-time recovery, metrics and follower databases.
  • Add-ons. Each one is a third-party service billed through the platform; most can be bought directly from the same vendor.
  • Logs and metrics. The platform aggregates process output and supports log drains. You will need an aggregator.
  • Review apps and pipelines. Per-pull-request environments and promotion between stages are features you may need to rebuild in CI.

The platform mechanics behind several of these are explained in Heroku dynos and buildpacks. If any item on the list is something your team would rather not own, that is useful information about whether to move at all.

Where teams go

DestinationWhat you keepWhat you take on
Another application platformGit push deployment, managed TLS, minimal operationsA different set of platform constraints and a new vendor relationship
Managed container serviceScaling and health checks handled by the providerContainer builds, registries, task definitions, networking
Plain cloud serversComplete control and predictable pricingEverything: patching, process supervision, certificates, monitoring
Managed KubernetesA portable deployment model and rich ecosystemA substantial permanent operations commitment

For most teams leaving on cost grounds, the middle two rows are the realistic answer. A container platform preserves most of the deployment ergonomics, while plain servers offer the largest saving and the largest increase in work. The comparison in Heroku versus DigitalOcean covers that middle ground, and the DigitalOcean account listings describe what the destination side includes.

Whichever you choose, containerise first. An application packaged as an image can be deployed to any of these destinations, which turns the platform choice into a reversible decision. Our guide to running Docker on a cloud server covers the groundwork.

Preparing the application

Applications built for this platform tend to follow good habits already, which makes the code side easier than teams expect. Configuration comes from the environment, the filesystem is treated as ephemeral, and processes are stateless. Those properties transfer directly.

The details that need attention are the platform-specific ones. Your application probably binds to a port supplied in an environment variable, which you now set yourself. The database connection string arrives as a config var from the add-on, and will now come from your secrets store. Any code that assumes the platform's log routing needs to write to standard output and let the collector handle the rest.

Replicate the Procfile explicitly. Each process type becomes a container command, a service definition or a systemd unit, including the release-phase task that runs migrations before the new version starts serving.

Finally, audit scheduled jobs. The scheduler add-on runs commands on a cadence, and those need a home: a cron entry, a scheduled task in your orchestrator, or a job runner inside the application.

Moving Heroku Postgres

The database is the part that determines your downtime, and the platform gives you reasonable tools.

For a straightforward move with a maintenance window, capture a backup with the CLI's pg_backups commands, download the dump and restore it into the destination with pg_restore. Test the whole sequence on a copy well before the real attempt, and time it.

For a shorter interruption, logical replication from the Heroku database to the destination is the better path, subject to the plan supporting it and the destination accepting the connection. The general approach, including the validation that must follow, is set out in database migration strategies.

Whichever route you take, verify sequences, extensions and roles on the destination before cutover. Extensions in particular are easy to miss, because the platform enables several by default that a fresh database will not have.

Switching over

Run both environments in parallel for a period before the switch, with the new one serving no production traffic but running the same code and connected to a replica of the data. This exposes configuration gaps while they are harmless.

On the day, lower DNS time-to-live in advance, enable maintenance mode on the platform, take the final database sync, point the domain at the new load balancer and verify. Keep the old application deployed but idle rather than deleting it, so reversal is a DNS change rather than a rebuild.

Watch for the integrations that hold your old hostname: webhook endpoints registered with payment providers, OAuth redirect URIs, and any partner allowlisting your outbound addresses. These are the most common cause of a partially successful cutover.

Plan the reverse path explicitly before you start, using the approach in migration testing and rollback plans. Cancel add-ons and the platform plan only after a full billing cycle on the new environment.

Key takeaways

  • List everything the platform does silently, routing, builds, process supervision, config, logs and review apps, before choosing a destination.
  • Containerise first so the destination decision stays reversible.
  • Expect the application code to transfer easily; the work sits in configuration, process definitions and scheduled jobs.
  • Choose the database path by downtime tolerance, and check extensions, roles and sequences on the destination.
  • Run the new environment in parallel before cutover, and keep the old application deployed but idle for a clean reversal.
  • Hunt down webhook endpoints, redirect URIs and partner allowlists that still reference the old hostname.

The vendor references worth reading first are the Heroku Postgres backups documentation and the Procfile reference, which together describe most of what you are replacing. Account details for the platform itself are in the Heroku account listings.

Questions about a cloud account?

Ask about products, variants, availability or purchasing on either channel.