Move from Heroku
Moving a Heroku app to velixir takes four steps: create the app, bring its config vars, move the database, and switch the domain. Most apps need no code changes, because velixir builds your source without a Dockerfile and passes config through environment variables, just as Heroku does.
Before you start
- Install the velixir CLI and run
velixir login. - Have the Heroku CLI signed in, and the Postgres client tools (
pg_restore,psql) installed locally. - Pick a quiet window for the database copy. Writes made on Heroku after the backup won't be carried over.
1. Create the app and deploy it
From your app's source directory:
velixir init
velixir deploy
velixir detects the language and builds the app. If you have a Procfile, its web line is used as the start command. Your app must listen on 0.0.0.0 on the port in PORT, which Heroku apps already do.
A few things work differently:
- Workers. Run each Heroku worker process as its own velixir app from the same source, with an environment variable your code reads to start the worker instead of the web server.
- Release phase. Don't rely on a
release:line. Run migrations as part of your start command, before the server starts. - Scheduler. Run scheduled jobs from inside your app (a cron library), or from a small worker app.
- Build-time config. Config vars reach the app when it runs, not while it builds.
2. Bring your config vars
heroku config -s -a your-heroku-app | velixir env import - --secret
That copies every config var in one go, stored as secrets. PORT is skipped because velixir sets it, and so is anything else velixir provides itself. Then remove the add-on URLs you're replacing (DATABASE_URL, REDIS_URL and the like) with velixir env unset, so the managed services you bind next take over. See Environment variables.
3. Back up your Heroku database
heroku pg:backups:capture -a your-heroku-app
curl -o latest.dump "$(heroku pg:backups:url -a your-heroku-app)"
Move your Postgres data
Create the database on velixir in the same project as the app, from the dashboard or with
velixir db create. Pick a plan with room for your data, and the same Postgres major version you run today or a newer one (15, 16 and 17 are available). Leave External access on so you can restore from your machine.Get its public connection string:
velixir db connect <database-id> --externalOr copy the External connection string from the database's page in the dashboard.
Restore your dump into it:
pg_restore --no-owner --no-acl --verbose -d "<velixir external connection string>" latest.dump--no-owner --no-aclmatter: your database's role owns everything it creates but isn't a superuser, so ownership and grants from the old host can't be replayed. An extension that needs a superuser to install may fail to restore; tell us which and we'll help.Bind the database to your app from the database's page in the dashboard, or with
velixir db bind <database-id> --app <app-id>. The app then getsDATABASE_URLpointing at the in-cluster address. Remove anyDATABASE_URLyou imported from the old host first, or your value wins over the binding.
The connection passes straight through to Postgres, encrypted end to end. If a single step (a large index build, say) runs for more than five minutes without sending anything, the connection can drop. For big databases, restore in parts (pg_restore --section=pre-data, then data, then post-data), or open a ticket and we'll help you run it.
Redis or Key-Value Store
Create a Valkey cache from the dashboard or with velixir cache create, and bind it to the app. Valkey speaks the Redis protocol, so Redis clients work unchanged. Cache contents usually aren't worth copying; let them rebuild.
4. Switch the domain
Redeploy with velixir deploy, check the app on its velixir.run address, then add your domain on the app's Domains tab and point DNS at velixir. See Custom domains. Keep the Heroku app running until DNS has moved over, then scale it down.
Stuck on something Heroku-specific? Open a ticket from the dashboard and we'll help you move it.