Preboot
Last updated May 24, 2023
Table of Contents
Preboot changes the standard dyno start behavior for web dynos. Instead of stopping the existing set of web dynos before starting the new ones, preboot ensures that the new web dynos are started (and receive traffic) before the existing ones are terminated. This can contribute to zero downtime deployments.
Preboot is only available on the Common Runtime to apps that are using professional dyno types (standard and performance). Applications using eco
or basic
dynos do not have access to preboot. Applications on Private Spaces can make use of rolling deploys.
This feature should be used carefully because it can lead to situations where you have two versions of your code base running side by side. For example, your web dynos could be running an old release while your workers are running a new release. Ensure that your code and database configuration support this behavior.
Enabling and Disabling Preboot
Preboot needs to be explicitly enabled on a per-app basis. To enable preboot:
$ heroku features:enable preboot -a <myapp>
Enabling preboot for myapp... done
To disable preboot:
$ heroku features:disable preboot -a <myapp>
Disabling preboot for myapp... done
Enabling and disabling preboot on your application will not trigger a restart.
To check if preboot is enabled:
$ heroku features -a <myapp>
=== App Features (myapp)
[+] preboot Provide seamless web dyno deploys [general]
Deploying with Preboot
Once preboot is enabled, you can create new releases (by deploying code or changing a config var) as usual, but you’ll see different behavior:
- Logs will show new dynos starting soon after the slug compile is finished. The output of
heroku ps
will immediately show the state (for example,starting
orup
) of the new dynos. Old dynos are still running but won’t appear inheroku ps
. - Approximately 3 minutes after the deploy completes (or 2 minutes after your app’s boot timeout limit, which defaults to 1 minute), HTTP requests will start routing to the new dynos and simultaneously stop routing to the old dynos.
- Shortly after the new dynos are fully live and serving user requests, the old dynos will be shut down. You’ll see them shut down in the logs as usual.
This behavior change only applies to the web
process type. Other dynos (such as workers) will continue to be shut down and restarted normally.
If you make database schema changes that require downtime, we recommend disabling the preboot feature, performing the changes and code push as usual, then re-enabling preboot.
Preboot in Manual or Automatic Dyno Restarts
Preboot behavior is slightly different between restarts caused by releases and manual or automatic dyno restarts such as cycling. You’ll see the following behavior when dynos are manually or automatically restarted:
- Logs show new dynos starting soon after the slug compile finishes. The output of
heroku ps
immediately shows the state (for example,starting
orup
) of the new dynos. Old dynos are still running but won’t appear inheroku ps
. - The new dynos start receiving requests as soon as it binds to its assigned port. At this point, both the old and new dynos are receiving requests.
- Approximately 4 to 6 minutes after the restart is invoked, the old dynos shut down. You see them shut down in the logs as usual.
Caveats
- Whoever is doing the deployment will have to wait a few minutes before the new code starts serving user requests. This happens later than it would without preboot (but in the meantime, user requests are still served by old dynos).
- There will be a short period (a minute or two) where
heroku ps
shows the status of the new dynos, but user requests are still being served by old dynos. - If you have a dyno that is in a bad state,
heroku restart
will start new dynos but not kill the old one until you stop sending restarts for 3 minutes or more.heroku ps:stop
can solve the problem immediately. - When you make releases with preboot, you will have two versions of your code running at the same time, overlapping for up to 3 minutes, although only one version will be serving user requests. You should be careful to make sure they interact gracefully. Some add-ons and other services limit the number of simultaneous connections so running twice as many dynos makes you more likely to hit such a limit. In particular, for Heroku Postgres, the recommended way around this would be to use Connection Pooling.
- When you make releases with preboot, Heroku switches the routing from the old dyno to the new dyno at one point. It is possible to have a very short time overlap where the requests go to both dynos during the switchover.
- When you do manual or automatic dyno restarts with preboot, your new dyno may start serving requests before it’s fully ready because it will start receiving requests as soon as it binds to its assigned port. This also applies to the case when you scale dynos, or switch dyno types.
- During a release, scaling and other dyno formation changes are not allowed. You must wait until preboot is complete.
- During a release triggered by a config var change, old dynos run with the old config var values. Make config var changes carefully, especially when performing database changes that modify the database connection string that your app is connecting to, such as promoting a new database. We don’t recommend using preboot on applications with Mini Heroku Data for Redis plans, or Essential Heroku Postgres plans due to these connection string changes. Premium plans have more stable addresses and include redirect features to minimize downtime when switching hosts due to a maintenance or failover.