Start from the Procfile and the release command
The Procfile names the process types: usually a web process and sometimes workers. A process type called release runs in a one-off dyno whenever a new release is created, except when the release is caused by a change to an add-on's config vars, so not every release runs it. Heroku's documentation says the release does not deploy if that command fails, leaving the current release in place. Migrations are a common use. Heroku advises migration scripts to use transactions, to check whether a migration was already applied and to take an advisory lock. The filesystem is ephemeral, so files written during the release phase are not carried into your dynos. A new host that never runs your release command will deploy code against an unmigrated database.
- Write down each process type and its start command.
- Write down what the release command does, and where its equivalent runs on the new host.
Config variables: list the names, never the values
Config vars are Heroku's environment variables, and add-ons often create some of them. The documentation says a provider may change an add-on's values at any time, so copying a value once is not a stable plan; read it where the new service provides it. Setting or removing a variable restarts the app and creates a release. For the inventory you need only the names and where each comes from. The values are secrets that you enter yourself on the new host.
- Group names by owner: the app, an add-on, a third-party service.
- Never paste a value into an email, a ticket or a chat.
- Check names that only a scheduled job reads: they are easy to miss.
If the matrix is wider than the box, scroll horizontally to read every column. Keyboard: focus the matrix and use Left/Right.
heroku config --json --app YOUR-APP-NAME | node -e "console.log(Object.keys(JSON.parse(require('fs').readFileSync(0,'utf8'))).join('\n'))"Scheduled jobs and add-ons need replacements, not copies
Heroku Scheduler runs commands as one-off dynos every ten minutes, hourly or daily, and the documentation says execution is expected but not guaranteed, with rare skips or double runs. It is an add-on, so the schedule is not in your code; look in the dashboard. Each job needs an equivalent on the new host and a decision about what happens if it runs twice. Heroku itself recommends a custom clock process where scheduled jobs are critical. For every other add-on, record what it provides, who pays for it and what replaces it.
- A job that runs on both hosts after the switch can duplicate emails or charges.
- A job that runs on neither shows up days later as missing data.
Decide a replacement for every item
Produce one list with a row for each process, release command, variable group, add-on and scheduled job, and a decision beside each: same, replaced by a named service, removed with your agreement, or unknown. An unknown is a question for the owner, not a gap to guess. Keep the list with the move so the cutover plan can say which side's workers and jobs run at each moment.
- Include the domain and any file storage as items.
- Mark items that only the account owner can discover.
What to send, and how the paid move is accepted
Send the language, the process names, the add-on names and the database size; do not send values, database URLs, a database backup or a Heroku login. The fixed job moves one web app and one database up to 20 GB, with no worker, scheduler, Redis or queue. An app that has any of those is not covered by a fixed-price outcome: ask for a quote that names each part. The job is accepted when a backup you restored passes the reconciliation, the new host builds the app, runs the release command, starts the web process with every variable name present and passes your named flows, the way back has been rehearsed, and the old app and the backup taken at the freeze stay unchanged until you sign off. Prices are untested proposals; payment follows the agreed checks.
Sources and limits
- Heroku Dev Center: release phase Checked 2026-10-11.
- A release process type in the Procfile runs in a one-off dyno whenever a new release is created, unless the release is caused by changes to an add-on's config vars; the release fails if the command exits with a non-zero status, leaving the current release in place.
- The release command has a 1-hour timeout and the filesystem is ephemeral.
- The documentation advises migration scripts to use transactions, check whether a migration was applied and take an advisory lock.
- Heroku Dev Center: config vars Checked 2026-10-11.
- Config vars are environment variables; add-ons usually set some, and their values can change at any time; setting one restarts the app and creates a release; total config data is limited to 64 KB.
- Heroku Dev Center: Heroku Scheduler Checked 2026-10-11.
- Scheduler runs one-off dynos every 10 minutes, hourly or daily; execution is expected but not guaranteed and a job can occasionally be skipped or run twice.
- Heroku recommends a custom clock process where scheduled jobs are critical.