Skip Navigation
Show nav
Dev Center
  • Get Started
  • Documentation
  • Changelog
  • Search
  • Get Started
    • Node.js
    • Ruby on Rails
    • Ruby
    • Python
    • Java
    • PHP
    • Go
    • Scala
    • Clojure
    • .NET
  • Documentation
  • Changelog
  • More
    Additional Resources
    • Home
    • Elements
    • Products
    • Pricing
    • Careers
    • Help
    • Status
    • Events
    • Podcasts
    • Compliance Center
    Heroku Blog

    Heroku Blog

    Find out what's new with Heroku on our blog.

    Visit Blog
  • Log inorSign up
Hide categories

Categories

  • Heroku Architecture
    • Compute (Dynos)
      • Dyno Management
      • Dyno Concepts
      • Dyno Behavior
      • Dyno Reference
      • Dyno Troubleshooting
    • Stacks (operating system images)
    • Networking & DNS
    • Platform Policies
    • Platform Principles
  • Developer Tools
    • Command Line
    • Heroku VS Code Extension
  • Deployment
    • Deploying with Git
    • Deploying with Docker
    • Deployment Integrations
  • Continuous Delivery & Integration (Heroku Flow)
    • Continuous Integration
  • Language Support
    • Node.js
      • Node.js Behavior in Heroku
      • Working with Node.js
      • Troubleshooting Node.js Apps
    • Ruby
      • Rails Support
      • Working with Bundler
      • Working with Ruby
      • Ruby Behavior in Heroku
      • Troubleshooting Ruby Apps
    • Python
      • Working with Python
      • Background Jobs in Python
      • Python Behavior in Heroku
      • Working with Django
    • Java
      • Java Behavior in Heroku
      • Working with Java
      • Working with Maven
      • Working with Spring Boot
      • Troubleshooting Java Apps
    • PHP
      • Working with PHP
      • PHP Behavior in Heroku
    • Go
      • Go Dependency Management
    • Scala
    • Clojure
    • .NET
      • Working with .NET
  • Databases & Data Management
    • Heroku Postgres
      • Postgres Basics
      • Postgres Getting Started
      • Postgres Performance
      • Postgres Data Transfer & Preservation
      • Postgres Availability
      • Postgres Special Topics
      • Migrating to Heroku Postgres
    • Heroku Key-Value Store
    • Apache Kafka on Heroku
    • Other Data Stores
  • AI
    • Heroku Inference
      • AI Models
      • Inference Essentials
      • Inference API
      • Quick Start Guides
    • Working with AI
    • Vector Database
  • Monitoring & Metrics
    • Logging
  • App Performance
  • Add-ons
    • All Add-ons
  • Collaboration
  • Security
    • App Security
    • Identities & Authentication
      • Single Sign-on (SSO)
    • Private Spaces
      • Infrastructure Networking
    • Compliance
  • Heroku Enterprise
    • Enterprise Accounts
    • Enterprise Teams
    • Heroku Connect (Salesforce sync)
      • Heroku Connect Administration
      • Heroku Connect Reference
      • Heroku Connect Troubleshooting
  • Patterns & Best Practices
  • Extending Heroku
    • Platform API
    • App Webhooks
    • Heroku Labs
    • Building Add-ons
      • Add-on Development Tasks
      • Add-on APIs
      • Add-on Guidelines & Requirements
    • Building CLI Plugins
    • Developing Buildpacks
    • Dev Center
  • Accounts & Billing
  • Troubleshooting & Support
  • Integrating with Salesforce
  • Extending Heroku
  • Platform API
  • Creating Slugs from Scratch

Creating Slugs from Scratch

English — 日本語に切り替える

Last updated December 03, 2024

Table of Contents

  • Create the slug
  • Create slug archive
  • Publish to the platform
  • Release the slug

This article describes creating slugs from scratch on a machine that you control, and then uploading and running those slugs on Heroku apps. Doing this is appropriate if full control over what goes into slugs is needed.

For most uses, however, we recommend using the build resource of the Platform API to transform source code into slugs. Using the build resource is generally simpler than creating slugs from scratch, and will cause slugs to be generated using the standard Heroku slug compiler and the standard Heroku buildpacks. Slugs generated using the standard build pipeline are more likely to be compatible and work on Heroku. For details on how to create slugs using the Platform API and the build resource, see Build and release using the API.

If you want to use the standard Buildpack and slug compilation process but want to re-use slugs in multiple apps, please see the Copying Slugs with the Platform API.

 

This article is only applicable to apps that use classic buildpacks.

Slugs and Stacks

Slugs on Heroku are specific to a particular stack. When creating slugs via the API, a stack can optionally be specified.

When creating slugs, you should be mindful of what Heroku stack you plan to deploy the slug on. Make sure that any binaries included in the slug are compatible with the Linux version that underpins the Heroku stack you are targeting.

Create the slug

Slugs are gzip compressed tar files containing a runnable Heroku application in the ./app directory. Slugs may contain files outside of ./app; however, they will be ignored when unpacked by Heroku. Slug size should not exceed the slug size limits.

In this example, we will demonstrate how to create, from scratch, slugs containing either Node.js, Ruby or Go apps. For all slugs, contents should be in the ./app directory, so first create and enter this directory:

$ mkdir app
$ cd app

Now add the actual app and any required dependencies. The details depends on the chosen app and framework.

If you’re following this guide, choose one language and complete the steps for that language only

Node.js

Get the Node.js runtime for x64 Linux:

$ curl http://nodejs.org/dist/v0.10.20/node-v0.10.20-linux-x64.tar.gz | tar xzv

Now add the code for the app in a file named web.js:

// Load the http module to create an http server
var http = require('http');

// Configure HTTP server to respond with Hello World to all requests
var server = http.createServer(function (request, response) {
  response.writeHead(200, {"Content-Type": "text/plain"});
  response.end("Hello World\n");
});

var port = process.env.PORT;

// Listen on assigned port
server.listen(port);

// Put a friendly message on the terminal
console.log("Server listening on port " + port);

Ruby

The Ruby project does not provide precompiled self-contained runtimes, so we’ll use one created by the Heroku Ruby team for the buildpack. It’s available at https://heroku-buildpack-ruby.s3.amazonaws.com/ruby-2.0.0.tgz.

Get the Ruby runtime:

$ mkdir ruby-2.0.0
$ cd ruby-2.0.0
$ curl https://heroku-buildpack-ruby.s3.amazonaws.com/ruby-2.0.0.tgz | tar xzv
$ cd ..

Add a very simple Ruby app to server.rb:

require 'webrick'

server = WEBrick::HTTPServer.new :Port => ENV["PORT"]

server.mount_proc '/' do |req, res|
    res.body = "Hello, world!\n"
end

trap 'INT' do
  server.shutdown
end

server.start

Go

Creating Go slugs is surprisingly simple. This is because the go build command produces standalone executables that do not require bundling any additional runtime dependencies. One caveat is that you have to cross-compile executables if you’re not creating the slug on the same architecture that Heroku uses (linux/amd64). Setting up the Go toolchain for cross-compilation is relatively simple.

Add the app in web.go:

package main

import (
    "fmt"
    "net/http"
    "os"
)

func main() {
    http.HandleFunc("/", hello)
    fmt.Println("listening...")
    err := http.ListenAndServe(":"+os.Getenv("PORT"), nil)
    if err != nil {
      panic(err)
    }
}

func hello(res http.ResponseWriter, req *http.Request) {
    fmt.Fprintln(res, "hello, world")
}

Now build an executable that will work on Heroku:

GOARCH=amd64 GOOS=linux go build web.go

Create slug archive

Change back to the parent directory of app and compress ./app (the ./ prefix is important) to create the slug:

$ cd ..
$ tar czfv slug.tgz ./app

Heroku currently has limited tar-file compatibility. Please use GNU Tar (and not bsdtar) when creating slug archives. You can check your tar version with tar --version. If you find that a slug created with GNU Tar fails to boot on Heroku, then feel free to open a support ticket to get help debugging the problem.

Publish to the platform

Start by creating the Heroku app that will be running this slug:

$ heroku create example-app
Creating example-app... done
http://example-app-1234567890ab.herokuapp.com/ | git@heroku.com:example.git

Publishing your slug to the platform is a two-step process. First, request that Heroku allocate a new slug for your app. When allocating the slug, use the process_types parameter to provide a list of runnable commands that are available in the slug being created. There is also a recommended checksum parameter to provide the checksum of the slug to ensure its integrity.

The process_types parameter has content similar to what is included in the Procfile that’s typically included in apps pushed to Heroku. The Procfile is not parsed when slugs are launched in dynos; instead they are parsed by the build system and the contents are passed in when the slug is created.

The process_types parameter depends on what kind of slug you created above:

  • Node.js: { "web": "node-v0.10.20-linux-x64/bin/node web.js" }
  • Ruby: {"web": "ruby-2.0.0/bin/ruby server.rb"}
  • Go: {"web":"./web"}

The -n flag tells curl to read the credentials for api.heroku.com from ~/.netrc and automatically sets the Authorization header. See the Getting Started with the Platform API for other authentication options.

$ curl -X POST \
-H 'Content-Type: application/json' \
-H 'Accept: application/vnd.heroku+json; version=3' \
-d '{"process_types":{"web":"node-v0.10.20-linux-x64/bin/node web.js"}}' \
-n https://api.heroku.com/apps/example/slugs
{
  "blob":{
    "method": "put",
    "url": "https://s3-external-1.amazonaws.com/herokuslugs/heroku.com/v1/d969e0b3-9892-4567-7642-1aa1d1108bc3?AWSAccessKeyId=..."
  },
  "commit":null,
  "created_at":"2013-10-08T22:04:13Z",
  "id":"d969e0b3-9892-3113-7653-1aa1d1108bc3",
  "process_types":{
    "web":"node-v0.10.20-linux-x64/bin/node web.js"
  },
  "updated_at":"2013-10-08T22:04:13Z"
}

Please note that the blob URL is not passed in the slug create request. Instead, it’s returned in the slug create response, and you can then use the URL to PUT your binary slug artifact.

For the second step we will use the blob URL provided in the response above to upload slug.tgz and make it available to the platform:

$ curl -X PUT \
-H "Content-Type:" \
--data-binary @slug.tgz \
"https://s3-external-1.amazonaws.com/herokuslugs/heroku.com/v1/d969e0b3-9892-4567-7642-1aa1d1108bc3?AWSAccessKeyId=..."

Release the slug

The slug is now uploaded to Heroku, but is not yet released to an app. To actually start running this slug, POST its id to the /apps/:app/releases endpoint:

$ curl -X POST \
-H "Accept: application/vnd.heroku+json; version=3" \
-H "Content-Type: application/json" \
-d '{"slug":"d969e0b3-9892-3113-7653-1aa1d1108bc3"}' \
-n https://api.heroku.com/apps/example/releases
{
  "created_at":"2013-10-08T16:09:54Z",
  "description":"deploy",
  "id":"a0ff4658-ec55-4ee2-96a9-8c67287a807e",
  "slug":{
    "id":"d969e0b3-9892-3113-7653-1aa1d1108bc3"
  },
  "updated_at":"2013-10-08T16:09:54Z",
  "user":{
    "email":"jane@doe.com",
    "id":"2930066e-c315-4097-8e88-56126f3d4dc1"
  },
  "version":3
}

The same slug can be released to multiple apps. This can be used for more advanced deployment workflows.

You can now see the new release in your app’s release history:

$ heroku releases --app example
=== example Releases
v3  deploy  jane@doe.com  2013/10/08 16:09:54 (~ 1m ago)
...

View your app in your browser to see it running with the newly released slug.

$ heroku open --app example

Keep reading

  • Platform API

Feedback

Log in to submit feedback.

Setting Up Apps Using the Platform API Getting Started with the Platform API

Information & Support

  • Getting Started
  • Documentation
  • Changelog
  • Compliance Center
  • Training & Education
  • Blog
  • Support Channels
  • Status

Language Reference

  • Node.js
  • Ruby
  • Java
  • PHP
  • Python
  • Go
  • Scala
  • Clojure
  • .NET

Other Resources

  • Careers
  • Elements
  • Products
  • Pricing
  • RSS
    • Dev Center Articles
    • Dev Center Changelog
    • Heroku Blog
    • Heroku News Blog
    • Heroku Engineering Blog
  • Twitter
    • Dev Center Articles
    • Dev Center Changelog
    • Heroku
    • Heroku Status
  • Github
  • LinkedIn
  • © 2025 Salesforce, Inc. All rights reserved. Various trademarks held by their respective owners. Salesforce Tower, 415 Mission Street, 3rd Floor, San Francisco, CA 94105, United States
  • heroku.com
  • Legal
  • Terms of Service
  • Privacy Information
  • Responsible Disclosure
  • Trust
  • Contact
  • Cookie Preferences
  • Your Privacy Choices