Hoppa till innehåll

Migration guide · From Heroku

Migrate from Heroku to SIAX

Heroku made deploys easy before anyone else did, and part of that simplicity is still hard to beat. What actually makes teams move is rarely the technology but the economics: per-dyno pricing, add-ons that each look cheap on their own and add up to a significant line item together, and a platform that has evolved slowly in recent years.

With us you run the web process and background processes as containers on App Hosting, the database as Managed Postgres, and whatever lacks a managed equivalent on a VPS. The monthly cost becomes predictable and you get root access where you need it.

The tricky part isn't the app but the add-on ecosystem. Heroku has made it easy to click in a service, and most teams have more add-ons than they remember. Each one has to be replaced individually, and a few have no obvious equivalent. Expect that part to take more time than the actual application move.

Time required

One day for an app with one web process and one Postgres. One to two weeks if you have five or more add-ons, background jobs and scheduled runs.

Downtime

The app can be moved without interruption if you run in parallel. The database requires a write window: a few minutes with dump and restore for a small database, longer for large ones. With logical replication you get it down to seconds.

01

How to do it

  1. 1

    Inventory dynos, add-ons and config vars

    Run heroku ps, heroku addons and heroku config for each app and save the output. Note the dyno type and count per process type, and which plan each add-on is on. This list is the spec for the new environment, and it's almost always longer than the team guesses.

  2. 2

    Replace the buildpack with a Dockerfile

    Heroku does a lot invisibly for you: installs dependencies, compiles assets, sets PORT and starts what's in the Procfile. All of that needs to be explicit in your Dockerfile. Bind to the PORT the environment specifies instead of a hardcoded port. Alternatively, you can run Cloud Native Buildpacks with the pack CLI if you want to keep the buildpack model a while longer.

  3. 3

    Replace each add-on individually

    Go through the list item by item. Heroku Postgres becomes Managed Postgres. Heroku Data for Redis becomes Redis or Valkey on a VPS, which you update and back up yourself. Papertrail and similar log and uptime services are replaced by our monitoring for checks and a log receiver of your choice. Outbound email via SendGrid is swapped for our email service or an external SMTP provider. Add-ons with no equivalent must either be kept as a standalone subscription or operated by you.

  4. 4

    Migrate Postgres

    First check which extensions you actually use, not which ones happen to be installed. Take a pg_dump in custom format and run pg_restore against the new instance, and test the whole path against a copy before touching production. For databases over a few tens of gigabytes, set up logical replication and switch the connection string once the replica has caught up. Note that Heroku's DATABASE_URL can be rotated and that the sslmode setting often differs.

  5. 5

    Move worker processes and scheduled jobs

    Each process type in the Procfile becomes its own deployment with us. Worker dynos become separate containers against the same queue. Heroku Scheduler is replaced by cron inside the container or a scheduled CI job. One-off runs you did with heroku run need a new routine, for example a shell in the running container or a manually triggered job.

  6. 6

    Set up deploy and secrets

    Connect the repo to Git and CI so that push to main builds the image and deploys. Move all config vars to the secrets manager and rotate them as part of the move, since they've now passed through an export. Verify the app starts with exactly the set of variables you intend to run in production, not a subset.

  7. 7

    Run in parallel, switch DNS and decommission

    Let the Heroku app keep taking production traffic while the new environment sits on a staging address. Compare logs, error rates and response times over at least a full day of real traffic. Then lower the TTL, switch DNS, and keep Heroku running for another week or so before scaling dynos to zero and canceling the add-ons.

02

What's actually tricky

  • Add-ons don't get replaced with a button. Every service has to be evaluated, replaced and tested individually, and a few have no good equivalent at all. This is routinely the biggest item in the timeline.
  • We don't have managed Redis as a product. Need Redis or Valkey? Run it on a VPS from 59 kr per month, with updates, memory limits and backup on you.
  • Buildpack magic is invisible until it disappears. Automatic asset compilation, PORT binding and injected environment variables stop happening on their own and need to be spelled out in the Dockerfile.
  • Heroku restarted your dynos daily. Code with slow memory leaks may have been masked by that cycle and only becomes visible once the container gets to live for weeks.
  • Review apps and pipelines don't exist as a built-in feature. You can build the equivalent with branch deploys in CI, but it's work you need to plan for, not a setting.
03

Cost example

An app with one web process, one worker, one Postgres, Redis and daily backup: App Hosting from 99 kr for the web and 99 kr for the worker, Managed Postgres from 89 kr, a VPS for Redis from 59 kr and backup 19 kr for 100 GB, so roughly 365 kr per month excluding VAT. The equivalent at Heroku with two Standard dynos, Postgres Standard-0 and a Redis plan runs around 1,200 to 1,400 kr per month at list price, and prices change continuously.

04

Frequently asked questions

Can we keep our buildpacks?
Not directly — we run containers. Either you write a Dockerfile, which we recommend long-term, or you build an OCI image from your existing buildpacks with the pack CLI. The second option shortens the migration but pushes the work down the road.
Do you have managed Redis?
No. Redis and Valkey run on a VPS or dedicated server. It ends up cheaper than a Heroku plan, but you take over operations: updates, memory policy, persistence and backup.
Do our Postgres extensions carry over?
The common ones do, including pg_stat_statements, pgcrypto, uuid-ossp and PostGIS. Unusual or Heroku-specific extensions need to be verified before you plan the cutover, not after. Send us the list from your database and we'll give you a concrete answer.
What do we do about Heroku Connect or other add-ons with no equivalent?
Either you keep the service as a standalone subscription with the vendor, or you replace the function with something you operate yourself. We don't pretend everything transfers cleanly, and that assessment should happen before you set a moving date.