---
title: Migrating from Heroku to Coolify
description: >-
  A practical guide to moving a Heroku app to Coolify. Concept mapping, config
  vars, Postgres migration with pg_dump, and a safe DNS cutover.
date: '2026-08-27'
lastUpdated: '2026-08-27'
keywords:
  - migrate heroku to coolify
  - heroku to coolify
  - leave heroku
  - heroku migration guide
  - heroku alternative
  - coolify postgres migration
  - heroku config vars to coolify
  - self-hosted PaaS migration
type: article
author: Ross Hill
locale: en_CA
site_name: MapleDeploy
slogan: Powerful hosting on Canadian soil
organization_url: 'https://mapledeploy.ca/'
logo: 'https://mapledeploy.ca//api/logo/lockup'
creator: MapleDeploy
publisher: MapleDeploy
founding_date: '2026-01-13'
email: hello@mapledeploy.ca
geo_region: CA-ON
geo_placename: Toronto
address_country: CA
area_served: Canada
application_category: DeveloperApplication
app_url: 'https://app.mapledeploy.ca'
llms_txt: 'https://mapledeploy.ca/llms.txt'
offers: >-
  Starter $45/mo, Pro $95/mo, Ultra $195/mo, Ultra 32 $395/mo, Ultra 64 $695/mo
  CAD
in_language: en-CA
canonical_url: 'https://mapledeploy.ca/blog/migrate-heroku-to-coolify'
---

Heroku made `git push` deploys normal. A generation of developers learned to ship on it, and the workflow it invented is still the one most platforms copy. If you're reading this, the platform probably isn't the problem. Something else changed: the bill, the resource ceiling, or where your data lives.

[Coolify](https://coolify.io) is one of the places people land. It's an open-source deployment platform that runs on a server you control, with the same connect-a-repo-and-deploy model. This guide covers the concept mapping, the migration sequence, and the parts Heroku was doing for you that you'll now own.

## Why people migrate

**Cost at scale.** Heroku bills per resource. A Basic dyno runs $7 USD/month for an always-on container, and Eco dynos share a pool of 1,000 dyno hours for $5 USD/month across your account, sleeping after a period of inactivity. Databases and add-ons are billed separately on top. None of that is unreasonable on its own. It's the addition that gets people: a web process, a worker, a database, a scheduler, a log drain, then the same again for staging. Check [Heroku's pricing page](https://www.heroku.com/pricing) for current figures before you model anything.

**Dedicated resources.** Dynos are containers sized by tier. If you want more memory or CPU, you move up a tier. On Coolify, you're deploying onto a server whose specs you picked, and every app and database on it shares those resources on your terms.

**Data residency.** Heroku's self-serve regions are US and EU. A Canadian region exists through Private Spaces, at a price point that rules it out for most teams. If your data needs to stay in Canada, that's a hard constraint rather than a preference. Our [full Heroku comparison](/compare/heroku) breaks down the side by side.

## Concept mapping

Most of what you know transfers. The names change.

| Heroku | Coolify |
|---|---|
| App | Application resource inside a project |
| Dyno | Container running your application |
| Procfile process types | One application per process, or a Docker Compose stack defining each service |
| Buildpacks | Nixpacks (auto-detects your stack) or your own Dockerfile |
| Config vars | Environment variables |
| Heroku Postgres add-on | A PostgreSQL database resource you create on your server |
| Heroku Scheduler | Scheduled tasks, defined with standard cron syntax |
| Release phase | Pre-deployment and post-deployment commands |
| Add-on marketplace | One-click services, or any Docker image you point it at |

Two mappings deserve a note.

**Release phase to deployment commands.** Coolify's pre-deployment command runs in the existing container before the new release goes out, and the post-deployment command runs in the newly built container afterward. Both are configured under the application's Advanced settings, and both execute with `sh -c`. Migrations that lived in your Procfile's `release` process type belong in the post-deployment command. Heroku ran release phase against the new slug, but Coolify's pre-deployment command runs against the old image, so a migration shipped in that same commit isn't in that container yet. Keep migrations backward compatible either way, because the new container starts serving before the post-deployment command finishes.

**Scheduler to scheduled tasks.** Coolify's scheduled tasks run a command inside a container you name, on a cron schedule, and they accept the full five-field syntax plus named schedules like `@daily`. Worth knowing: they're container-scoped. Heroku Scheduler ran each job in its own one-off dyno, while Coolify execs into the running container, so your app has to be up for the task to fire. If you need something to run on the host rather than inside a container, that's not what this feature does.

## The migration sequence

Do this in order. The point is that nothing is irreversible until the last step.

1. **Inventory what you have.** Run `heroku config -s` to dump your config vars and `heroku addons` to list every add-on. Write down your Procfile process types, any release phase command, your Scheduler jobs, and your custom domains. Lower the TTL on those DNS records now so the cutover is fast later.
2. **Stand up the app on Coolify from the same repo.** Connect your Git provider, create a project, add the repo as an application. If you have a Dockerfile, use it. If you were relying on buildpacks, start with Nixpacks and see how far it gets you. Our [Coolify deployment walkthrough](/blog/deploy-app-coolify-guide) covers build method selection, port configuration, and the gotchas.
3. **Port the environment variables.** Paste them in, minus the ones Heroku generated for you. `DATABASE_URL` and add-on credentials will be replaced with values from your own services. Watch for variables your framework needs at build time rather than runtime, since those need to be marked as build variables.
4. **Migrate the Postgres data.** Create a PostgreSQL database in Coolify first, then move the data. At a high level: `pg_dump` from your Heroku database connection string in custom format, then `pg_restore` into the new database with `--no-owner --no-acl` so it doesn't try to recreate Heroku's roles. Run `pg_dump` and `pg_restore` from a Postgres release at least as new as the newer of the two servers, since older client tools refuse to read a newer one. Do a throwaway run now to catch schema problems, and a final run at cutover.
5. **Test on the temporary URL.** Coolify gives every application a temporary URL before you attach a domain. Exercise the real paths: logins, background jobs, file uploads, scheduled tasks, anything that touches an external API. This is the step people rush, and it's the one that catches the missing environment variable.
6. **Cut over DNS.** Put the Heroku app in maintenance mode and scale any worker dynos to zero (maintenance mode only blocks web traffic; workers and Scheduler jobs keep running), take a final dump, restore it, then point your A record at your Coolify server. That combination is what makes the final dump consistent, so treat it as a planned write freeze and time the throwaway restore in step 4 to size it. With a low TTL, most traffic follows within minutes. Coolify provisions the Let's Encrypt certificate once DNS resolves.
7. **Keep Heroku running.** Don't delete anything for at least a week. Leave the app and its database in place, paying for it, until you've watched a full cycle of traffic, backups, and scheduled jobs run clean on the new setup.

8. **Decommission.** Remove add-ons, delete the app, cancel what's left. Keep one final Heroku backup somewhere off-platform before the database goes.

## What you take on

Here's the honest part. Heroku does real work that becomes yours the moment you self-host.

**Platform maintenance.** OS patches, Docker upgrades, Coolify updates, disk space, backup verification, uptime monitoring. Heroku did all of this invisibly and charged you for it inside the dyno price. On a VPS you rented yourself, it's your Saturday.

**Buildpack behaviour.** Heroku's buildpacks encode years of accumulated knowledge about how specific frameworks want to be built. Coolify's automatic detectors, Nixpacks and Railpack, cover a lot of standard projects. When neither matches your setup, you're writing the Dockerfile yourself. That's more control and more work.

**Add-on ecosystem.** Heroku's marketplace gives you third-party services with their own support and billing. On Coolify you deploy the equivalents onto your own server through one-click services or any Docker image. Broader coverage, but you're the one keeping them running.

The maintenance half of that list is what a managed Coolify host takes back off you. The platform layer gets handled, and you keep the dedicated server and the open-source stack underneath.

## Where MapleDeploy fits

MapleDeploy runs managed Coolify on [Canadian infrastructure](/canadian-hosting) in Toronto. We handle the VM, OS updates, security patches, monitoring, and weekly snapshots. You get the deployment platform without the server administration.

Flat CAD pricing, starting at $45/month for a dedicated 4 GB VM with databases, SSL, and deploys included. Deploy as many apps and databases as the server can hold, with no per-resource billing to forecast. See [our pricing](/#pricing) for the full plan list.

{% cta-section title="Move your first app over" %}
30-day free trial on Starter and Pro. Point Coolify at your repo, test on the temporary URL, cut over when you're ready.
{% /cta-section %}
