Heroku Go Support
Last updated September 26, 2024
Table of Contents
This document describes the general behavior of Heroku as it relates to the recognition and execution of Go applications. For a more detailed explanation of how to deploy an application, see Getting Started with Go on Heroku.
Supported Dependency/Vendor Managers
The currently supported dependency/vendor managers are:
- Go Modules
- godep (deprecated)
- govendor (deprecated)
- gb (deprecated)
- dep (deprecated)
Activation
The Heroku Go buildpack is used when an application meets one of the following requirements:
- has a
go.mod
file, identifying the application as being managed by Go Modules - has a
Godeps/Godeps.json
file, identifying the application as being managed by godep; - has a
vendor/vendor.json
file, identifying the application as being managed by govendor; - has a
src
directory, which has sub directories, contains one or more.go
files, identifying the application as being managed by gb.
When a deployed application is recognized as a Go application, Heroku responds with -----> Go app detected
, like so:
$ git push heroku master
...
remote: -----> Go app detected
...
We do basic structural validation of the various metadata files (go.mod
, Godeps.json`, etc) before attempting to use them. If there is an error it will be displayed like so:
$ git push heroku master
...
remote: Compressing source files... done.
remote: Building source:
remote:
remote: -----> Go app detected
remote: -----> Checking Godeps/Godeps.json file.
remote: parse error: Expected value before ',' at line 4, column 15
remote: ! Bad Godeps/Godeps.json file
remote:
remote: ! Push rejected, failed to compile Go app
...
Go versions
Heroku makes a number of different versions of the Go toolchain available. The currently supported versions listed here. Any version is available for use, but support is generally only provided for the latest current minor release of the last 2 major versions.
The major release identifier is used to represent the latest release in that series. Example: go1.22
will expand to the latest go 1.2 release that Heroku supports at the time the code was built, go1.22.4
, go1.22.5
, go1.22.6
, etc.
If you need to select a specific minor revision (e.x. go1.21.8
) for any reason you will need to hand edit the appropriate metadata file or set the $GOVERSION
environment variable, depending on the dependency manager you use:
- Go Modules
- godep
- govendor
- gb
- dep (community supported*)
In the rare case that you need to pin to the first release of a major version add a .0
to the version identifier. Example: go1.23.0
will pin an app’s go version to go1.23
.
Passing a symbol (and optional string) to the linker
Heroku supports the Go linker’s ability (-X symbol value) to set the value of a string at link time. This can be done by setting $GO_LINKER_SYMBOL
and $GO_LINKER_VALUE
in the application’s config before pushing code. If $GO_LINKER_SYMBOL
is set, but $GO_LINKER_VALUE
isn’t set then $GO_LINKER_VALUE
defaults to $SOURCE_VERSION
.
This can be used to embed the commit SHA, or other build specific data directly into the compiled executable.
Other build time behavior
Various aspects of the build can be controlled via several application config vars. Below is a list of the vars that are not covered elsewhere in this doc and what they control:
CGO_CFLAGS
,CGO_CPPFLAGS
,CGO_CXXFLAGS
andCGO_LDFLAGS
: These are the standard CGO flags as described here.GOPROXY
,GOPRIVATE
, andGONOPROXY
: These and the standard environment variables that configure use of module proxies as described here.GOVERSION
: Provides an override to the go version to use.GO_INSTALL_PACKAGE_SPEC
: Overrides the package spec passed togo install
with this value. This is useful when you have a large repo, but only want to compile a sub section of it.GO_INSTALL_TOOLS_IN_IMAGE
: When set totrue
, installs the go tool chain into the slug at$HOME/.heroku/go
, set’s$GOROOT=$HOME/.heroku/go
and includes$GOROOT/bin
in your$PATH
. Normally the go tools are not installed in the slug. This increases the slug size by about 81MB.GO_SETUP_GOPATH_IN_IMAGE
: When set totrue
$GOPATH=$HOME
is set and user code is placed in the appropriate location inside of the$GOPATH
(e.g.$GOPATH/src/github.com/heroku/go-getting-started
). When the dyno starts the working directory will be set to root of the user code. Normally the buildpack keeps user code in$HOME
. This is most useful when used in conjunction withGO_INSTALL_TOOLS_IN_IMAGE=true
so that there is a fully functioning go workspace and tool chain inside of the dyno.
Each of the above config vars need to be set on an application before pushing code and code must be pushed after these config vars are set for them to take effect.
Runtime behavior
Starting with go1.5 and newer, the buildpack does not set any Go runtime environment variables. You can set these environment variables on your application’s config and the application will be restarted with them in place. For go1.4 and older a default $GOMAXPROCS
will be set, depending on the size of your dyno. This can be overridden by using heroku config:set
to set a value for GOMAXPROCS
.
The runtime environment does not have a copy of the go tool chain or the compiled package files (*.a
) as the build pack does not copy them into the slug.
Static Assets & Files
Anything included in your git repository is available at runtime and can be served from the local filesystem using Go’s http.FileServer
or framework equivalent. Tools like go-assets, go-bindata & statik are not required.
Default process types
Heroku will add default process types if and only if all of the following conditions are met:
- The application uses Go modules
- The application does not already have a Procfile
- One or more Go packages were detected in the project
If Heroku detects one Go package, Heroku will add that package as a process type with the name web
. If Heroku detects multiple Go packages, Heroku will add a process type for each package using the name of the package.
To select or override the process types for your application, use a Procfile. See one of the Go tutorials for information on setting up your Procfile.
Add-ons
No add-ons are provisioned by default. If you need a SQL database for your app, add one explicitly:
$ heroku addons:create heroku-postgresql
Vendor directory support
Builds use the contents of the vendor/
directory when compiling as if they are in your $GOPATH
. If you choose to vendor, be careful when specifying the package path(s); ./...
matches all packages, which may include those in vendor/
. Heroku suggests putting individual main packages for executables inside of subdirectories of the cmd
directory like detailed in this blog post.
Vendoring additional main packages
Various vendoring tools can save additional packages beyond those in your local project into your project’s vendor directory. This is useful when you want to include, compile and install additional main packages. A common usage is to include a package like migrate to manage database migrations.
Go Modules
To install dependencies that aren’t imported into your application’s Go source code, you’ll need to add a Heroku build directive to your go.mod
. Learn more about go.mod
Heroku build directives here. For example:
// +heroku install ./cmd/... github.com/golang-migrate/migrate
Godep
To have godep save additional packages, those packages must be installed in your $GOPATH and included on the command line every time godep save
is run like so: godep save ./cmd/... github.com/golang-migrate/migrate
. The resulting changes to Godeps/Godeps.json
and either vendor/
or Godeps/_workspace
need to be committed.
On the next push Heroku will then install both ./cmd/...
and github.com/golang-migrate/migrate
.
govendor
govendor can fetch and save additional packages beyond those in your local project directly into your vendor/
directory like so: govendor fetch github.com/golang-migrate/migrate
.
Additionally, the heroku build configuration section of vendor.json
needs to have the additional packages added to the heroku.install
array like so:
...
"heroku" : {
...
"install": [
"./cmd/...",
"github.com/golang-migrate/migrate"
]
},
...
The changes to vendor/*
need to be committed. On the next push Heroku will then install both ./cmd/...
and github.com/golang-migrate/migrate
.
Going further
The Heroku Go buildpack is open source. For a better technical understanding of how the buildpack works, check out the source code at github.com/heroku/heroku-buildpack-go.