Buildpack API

Last Updated: 17 June 2015

Table of Contents

If you have questions about the build process on Heroku, consider discussing it in the Build forums.

Buildpacks are the scripts that power app builds on Heroku. Check out the Buildpacks article for an overview of what role buildpacks play on the Heroku platform.

Buildpack API

We encourage buildpack developers to use sh or bash to ensure compatibility with future Heroku stacks.

A buildpack consists of three scripts:

  • bin/detect: Determines whether to apply this buildpack to an app.
  • bin/compile: Used to perform the transformation steps on the app.
  • bin/release: Provides metadata back to the runtime.



bin/detect BUILD_DIR

The name sent to stdout will be displayed as the application type during push.


This script takes BUILD_DIR as a single argument and should return an exit code of 0 if the app present at BUILD_DIR can be serviced by this buildpack. If the exit code is 0, the script should print a human-readable framework name to stdout.



# this pack is valid for apps with a hello.txt in the root
if [ -f $1/hello.txt ]; then
  echo "HelloFramework"
  exit 0
  exit 1





The contents of CACHE_DIR will be persisted between builds. You can cache the results of long processes like dependency resolution here to speed up future builds.

This script performs the buildpack transformation. BUILD_DIR will be the location of the app and CACHE_DIR will be a location the buildpack can use to cache build artifacts between builds.

All output received on stdout from this script will be displayed to the user (for interactive git-push builds) and stored with the build.

The application in BUILD_DIR along with all changes made by the compile script will be packaged into a slug.

ENV_DIR is a directory that contains a file for each of the application’s configuration variables. These are the same configuration variables that are injected into the apps runtime environment.

The application config vars are passed to the buildpack as an argument (versus set in the environment) so that the buildpack can optionally export none, all or parts of the app config vars available in ENV_DIR when the compile script is run. Exporting the config can be scoped to only certain steps in the compile script or to the entire compile phase. The reason application config vars are passed to the compile script in individual files is to make it easier for buildpacks to correctly handle config vars with multi-line values

The name of the file is the config key and the contents of the file is the config value. The equivalent of config var S3_KEY=8N029N81 is a file with the name S3_KEY and contents 8N029N81.

Below is a Bash function demonstrating how to export the content of the ENV_DIR into the environment.

export_env_dir() {
  if [ -d "$env_dir" ]; then
    for e in $(ls $env_dir); do
      echo "$e" | grep -E "$whitelist_regex" | grep -qvE "$blacklist_regex" &&
      export "$e=$(cat $env_dir/$e)"

Use the regular expressions to blacklist or whitelist config keys for export. For example, runtime config vars like PATH can sometimes conflict with build tools so blacklisting that might be a good idea. Whitelisting is recommended if you know that builds will only require a specific subset of config vars (like DATABASE_URL) to run.

The following environment variables are available during the compile phase:

  • STACK: see the Stacks section below for details on how to use this
  • SOURCE_VERSION: the “version” of the source code currently being built. For git-push builds, this is the git commit SHA-1.


Buildpack developers are encouraged to match the Heroku push style when displaying output.

-----> Main actions are prefixed with a 6-character arrow
       Additional information is indented to align

Whenever possible display the versions of the software being used.

-----> Installing dependencies with npm 1.0.27



indent() {
  sed -u 's/^/       /'

echo "-----> Found a hello.txt"

# if hello.txt has contents, display them (indented to align)
# otherwise error

if [ ! -s $1/hello.txt ]; then
  echo "hello.txt was empty"
  exit 1
  echo "hello.txt is not empty, here are the contents" | indent
  cat $1/hello.txt
fi | indent



bin/release BUILD_DIR


addons will only be applied the first time an app is deployed.

BUILD_DIR will be the location of the app.

This script returns a YAML formatted hash with two keys:

  • addons is a list of default addons to install.
  • default_process_types is a hash of default Procfile entries.

This script will only be run if present.



cat << EOF
  - heroku-postgresql:dev
  web: bin/node server.js

Of course, rather than using default_process_types, it’s simpler to just write a default Procfile if one isn’t provided.

Default config values

To add default config values, create a .profile.d script. In most cases it’s best to defer to an existing value if set.

Example .profile.d/

# default NODE_ENV to production
export NODE_ENV=${NODE_ENV:production}

# add node binaries to the path


Use caution when storing large amounts of data in the CACHE_DIR as the full contents of this directory is stored with the git repo and must be network-transferred each time this app is deployed. A large CACHE_DIR can introduce significant delay to the build process.

The bin/compile script will be given a CACHE_DIR as its second argument which can be used to store artifacts between builds. Artifacts stored in this directory will be available in the CACHE_DIR during successive builds. CACHE_DIR is available only during slug compilation, and is specific to the app being built.

If the build pack does intend to use a cache, it should create the CACHE_DIR directory if it doesn’t exist.

Build packs often use this cache to store resolved dependencies to reduce build time on successive deploys.

Heroku users can use the heroku-repo plugin to clear the build cache created by the buildpack they use for their app


Heroku supports multiple runtime stacks. Example stacks are Cedar, based on Ubuntu 10.04, and Cedar-14, based on Ubuntu 14.04.

If you’re maintaining a buildpack, it’s your responsibility to make sure that the buildpack can create slugs that works on all the stacks that Heroku supports. When Heroku runs buildpacks to create slugs for an app, the build is always run in a dyno using the same stack as the app that the build is running for. In addition, a STACK environment variable is available during the compile phase so that a buildpack can determine the destination stack for the build. Example STACK values are cedar or cedar-14.

If your buildpack does not support a particular stack, the compile script can optionally print an error and exit with a non-zero exit code. Heroku recommends supporting all stacks, however.

Buildpacks should use the STACK variable to selectively pull binaries and other dependencies appropriate for that stack. Typically, binaries that are vendored in by buildpacks have to be built in different versions for each stack to ensure compatibility. See the Binaries section below for details.


A buildpack is responsible for building a complete working runtime environment around the app. This may necessitate including language VMs and other runtime dependencies that are needed by the app to run.

When building and packaging dependencies, make sure they are compatible with Heroku’s runtime environment. Typically, one set of binaries for each stack on Heroku and vendor in the appropriate set for the app currently being built. One way to do that is to build dependencies in Heroku dynos, for example by using heroku run.


Buildpacks may be published to the buildpack catalog service using the heroku-buildpacks plugin.

Example Buildpacks

The easiest way to get started creating a buildpack is to examine or fork one of the many existing buildpacks: * Default Buildpacks * Third-party Buildpacks

Problems or questions

If you’re trying to create a buildpack and run into problems or have questions along the way, please submit them to Stack Overflow.