Heroku Labs: preboot

Last Updated: 01 May 2013

This article is a work in progress, or documents a feature that is not yet released to all users. This article is unlisted. Only those with the link can access it.

Table of Contents

This Heroku Labs feature provides seamless deploys by booting web dynos with new code before killing existing web dynos.

Use case

Some apps take a long time to boot up, and this can cause unacceptable delays in the user experience while serving HTTP requests during deployment.

Overview

The standard sequence of events when deploying a new app is:

  1. Code push
  2. Run buildpack; store slug
  3. Pause routing service
  4. Kill old dynos
  5. Boot new dynos
  6. Resume routing service

This feature helps you avoid the user-facing downtime that happens between steps 3 and 6 above.

With the preboot feature enabled, the sequence looks like this:

  1. Code push
  2. Run buildpack; store slug
  3. Boot new dynos
  4. Switch routing
  5. Kill old dynos

Details

Prerequisites

Before you begin using this feature, use Production Check to ensure that your existing production app follows best practices for maximizing availability. In particular, this feature is only suitable for Cedar apps; if your app runs on Aspen or Bamboo, you shouldn’t use preboot.

We suggest you test any proposed changes on a staging app before trying preboot on your production app.

Note: this feature will not fix or cover up any errors, including H12 request timeout and H20 app boot timeout. Make sure you can deploy and restart your app without seeing any error codes. If you routinely see errors when deploying your app, it's important to fix them before trying to use this feature.

Enabling

$ heroku labs:enable -a myapp preboot
Enabling preboot for myapp... done
WARNING: This feature is experimental and may change or be removed without notice.

Disabling

$ heroku labs:disable -a myapp preboot
Disabling preboot for myapp... done

Once it’s enabled, you can use git push heroku master as usual, but you’ll see different behavior than before.

  • Logs will show new processes starting soon after the slug compile is finished. The output of heroku ps will immediately show the state (for example, starting or up) of the new dynos; old dynos are still running but won’t appear in heroku ps.
  • Approximately 3 minutes after the git push completes, HTTP requests will start routing to the new code and simultaneously stop routing to the old code.
  • Some time after the new code is fully live and serving user requests, the old dynos will be killed. You’ll see them killed in the logs as usual.

This behavior change only applies to the web process type. Other dynos (such as workers) will continue to be killed and restarted normally. It also applies any time the web dynos get restarted, regardless of the cause. So git push, heroku config:add, and heroku restart all use this behavior.

If you make schema changes that require downtime, we recommend disabling the preboot feature, performing the changes and code push as usual, then re-enabling preboot.

Caveats

  • You must have at least two web dynos to use this feature. If you have your web process type scaled to 1 or 0, preboot will be disabled.
  • 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 meanwhile, user requests are still served promptly by old dynos).
  • There will be a short period (a minute or two) where heroku ps shows the status of the new code, but user requests are still being served by old code.

You'll have two versions of your code running at the same time, overlapping for up to 2 minutes, although only one at a time 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; running twice as many dynos makes you more likely to hit such a limit.

This feature doesn't attempt to help with database migrations.