Heroku Ruby Support
Last updated May 25, 2023
Table of Contents
Heroku is capable of running Ruby applications across a variety of Ruby implementations and includes support for framework-specific workflows.
This document describes the general behavior of Heroku as it relates to the recognition and execution of Ruby applications. For framework specific tutorials please see:
General support
The following support is provided, irrespective of the type of Ruby application deployed.
Activation
The Heroku Ruby Support will be applied to applications only when the application has a Gemfile
in the root directory. Even if an application has no gem dependencies it should include an empty Gemfile
to document that your app has no gem dependencies.
Particular actions, documented in subsequent sections, are taken depending on the type of application deployed, which is determined by the following rules:
- Presence of
Gemfile
indicates a Ruby application - Presence of
config.ru
indicates a Rack application - Presence of
config/environment.rb
indicates a Rails 2 application - Presence of
config/application.rb
containing the stringRails::Application
indicates a Rails 3 application
Libraries
The following libraries are used by the platform for managing and running Ruby applications and cannot be specified. For application dependency resolution and management, bundler is installed based on the contents of your Gemfile.lock
. If you have a BUNDLED WITH
in your Gemfile.lock
then you will receive a different version of Bundler:
- Applications specifying Bundler 2.x in their
Gemfile.lock
will receive bundler: 2.3.25 - Applications specifying Bundler 1.x in their
Gemfile.lock
will receive bundler: 1.17.3 - Applications with no
BUNDLED WITH
in theirGemfile.lock
will default to bundler: 1.17.3
For more information on available settings see Bundler configuration. For more information on why we only support a specific set of bundler versions, please see this article about your Bundler version.
Environment
The following environment variables will be set:
GEM_PATH
=>vendor/bundle/#{RUBY_ENGINE}/#{RUBY_ABI_VERSION}
LANG
=>en-us
PATH
=>bin:vendor/bundle/#{RUBY_ENGINE}/#{RUBY_ABI_VERSION}/bin:/usr/local/bin:/usr/bin:/bin
DISABLE_SPRING
=>1
GEM_PATH
is set to the bundler gem vendor directory.
Process types
The following two process types are always made available:
rake: bundle exec rake
console: bundle exec irb
Build behavior
When an application is deployed, the build phase configures the underlying Rack or Rails application to use the provisioned database if a config
directory exists, and a RAILS_ENV
or RACK_ENV
environment variable is present. Prior to ActiveRecord 4.1, which is used by Rails 4.1+, a database.yml
file will be created . If a database.yml
file already exists, it will be replaced with ActiveRecord 4.1. The database.yml
file is created as Ruby code that dynamically creates its output by parsing the DATABASE_URL
environment variable. In ActiveRecord 4.1+ DATABASE_URL
support is baked in. For more information see configuring database connections and the pull request that added DATABASE_URL support
At the end of the build, the application will be checked for potentially problematic application configuration via the rails runner
interface.
JRuby
For JRuby, you can customize the options passed to the JVM during the build by setting the config var JRUBY_BUILD_OPTS
. A common value is --dev
, which optimizes the runtime for short processes like those executed by Bundler and Rake.
Ruby versions
Heroku makes a number of different Ruby implementations available. You can configure your app to select a particular runtime.
Default Ruby version for New Apps
If your Gemfile
does not contain a ruby
entry, you will get MRI 3.1.4
.
Default rubies are locked into the app until you specify a Ruby version. For example, if your app is using a default Ruby version of 3.0.3
, you will continue to stay on 3.0.3
.
We highly recommend specifying a Ruby version in your Gemfile and not relying on the default Ruby version.
Supported runtimes
Heroku supports the following Ruby versions and the associated Rubygems. A supported version means that you can expect our tools and platform to work with a given version. It also means you can receive technical support. Here are our supported Ruby versions:
MRI:
3.0.6
, Rubygems:3.2.33
(Heroku-20 only)3.1.4
, Rubygems:3.3.26
3.2.2
, Rubygems:3.4.10
When a Ruby version reaches EOL security patches will no longer be available. We highly recommend running on a version of Ruby that is actively supported by Ruby core.
JRuby:
9.1.17.0
, Ruby Versions: [2.3.3
]9.2.21.0
, Ruby Versions: [2.5.8
]9.3.10.0
, Ruby Versions: [2.6.8
]9.4.1.0
, Ruby Versions: [3.1.0
]
JRuby versions support multiple ruby versions listed below. You need to specify one in your Gemfile. JRuby runs on the JVM which is also installed alongside JRuby. For a list of supported Java versions and details on how to configure specific versions, see the Java support article.
For more information on the JVM environment and available JVM options (such as JAVA_TOOL_OPTIONS
) see Heroku’s Java Support on Dev Center.
For advanced JDK options, such as using the Zulu JDK or running jmap
, you must add the heroku/jvm
buildpack as the first buildpack on your app.
Selecting a runtime
Please see our Ruby Versions document for instructions on how to specify your Ruby version.
The Ruby runtime that your app uses will be included in your slug, which will affect the slug size.
Unsupported Ruby versions
The following is a list of runtime versions present for each stack. These versions are no longer receiving updates from Ruby core and do not fall under the Heroku Ruby support policy.
On the
heroku-20
stack:- 2.5.x (EOL):
2.5.8
to2.5.9
- 2.6.x (EOL):
2.6.6
to2.6.9
- 2.7.x (EOL):
2.7.1
to2.7.8
- 3.0.x:
3.0.0
to3.0.5
- 3.1.x:
3.1.0
to3.1.3
- 3.2.x:
3.2.0
to3.2.1
- 3.3.x:
3.3.0-preview1
(use3.3.0
in the Gemfile)
- 2.5.x (EOL):
On the
heroku-22
stack:- 3.1.x:
3.1.0
to3.1.3
- 3.2.x:
3.2.0
to3.2.1
- 3.3.x:
3.3.0-preview1
(use3.3.0
in the Gemfile)
- 3.1.x:
This means that while 2.5.9 is no longer “supported” on the Heroku-20 stack, it is still available for use at your own risk. Heroku always recommends using a supported Ruby version.
If your version of a library such as Rails does not work on a supported Ruby version, you may need to use a service such as Rails LTS that provides maintained version of older releases for a fee. The Rails LTS project is not affiliated with Heroku or with Rails Core.
Rails Version Support
Heroku’s support of Rails versions mirrors the Rails Core version support. We officially support the last three minor releases versions of Rails (for example 6.0.x, 5.2.x, and 5.1.x). Heroku does not sunset availability for older Rails versions. This means that any version of Rails that has ever been able to deploy on the platform can still be used on the platform today. The one limitation of this guarantee is that we cannot promise that older versions of Rails will work on the oldest available Ruby version on a given stack.
For example, if Rails 3.2 cannot run on Ruby 2.4.10 or higher then you will be unable to run a Rails 3.2 application on the Heroku-18 stack. We do not maintain version compatibility information between Ruby and Rails at this time.
If your version of a library such as Rails does not work on a supported Ruby version, one option may be to use a service such as Rails LTS that provides maintained version of older releases for a fee. The Rails LTS project is not affiliated with Heroku or with Rails Core.
If you’re not using a Rails Core officially supported version or a LTS supported version it means that your application likely has security vulnerabilities that are unpatched. We recommend always staying on an officially supported Rails version.
Ruby applications
Pure Ruby applications, such as headless processes and evented web frameworks like Goliath, are fully supported on Heroku.
Activation
When a deployed application is recognized as a pure Ruby application, Heroku responds with -----> Ruby app detected
.
$ git push heroku master
-----> Ruby app detected
Add-ons
If you created your account before May 15, 2023 or if you asked Heroku Support to enable Heroku Postgres auto-provisioning for your account, see Ruby Database Auto-Provisioning.
Process types
No default web
process type is created if a pure Ruby application is detected.
Rack applications
Rack applications behave like Ruby applications, with the following additions.
Activation
A root-level config.ru
file specifies the existence of a Rack application. Applications recognized as Rack apps are denoted with a -----> Ruby/Rack app detected
at deploy-time.
$ git push heroku master
-----> Ruby/Rack app detected
Environment
The following additional environment variable will be set:
RACK_ENV
=> “production”
Add-ons
Adds the same add-ons as a “Ruby” app.
Process types
If you don’t include a Procfile
, Rack apps will define a web process type at deploy time:
web: bundle exec rackup config.ru -p $PORT
On Heroku, we recommend Puma as the webserver. Regardless of the webserver you choose, production apps should always specify the webserver explicitly in the Procfile
.
As a special case to assist in migration from Bamboo, Ruby apps which bundle the thin
gem will get this web process type:
web: bundle exec thin start -R config.ru -e $RACK_ENV -p $PORT
Rails 2.x applications
Activation
An app is detected as a Rails 2.x app when the Gemfile.lock
file contains a rails
gem, and the gem version is greater than or equal to 2.0.0, and less than 3.0.0. Apps recognized as Rails 2.x apps are denoted with a -----> Ruby/Rails app detected
at deploy-time.
$ git push heroku master
-----> Ruby/Rails app detected
Environment
The following additional environment variables will be set:
RAILS_ENV
=> “production”RACK_ENV
=> “production”
Add-ons
Adds the same add-ons as a “Ruby” app.
Process types
If you don’t include a Procfile
, Rails 2 apps will define a web process type at deploy time:
web: bundle exec ruby script/server -p $PORT
On Heroku, we recommend Puma as the webserver. Regardless of the webserver you choose, production apps should always specify the webserver explicitly in the Procfile
.
As a special case to assist in migration from Bamboo, Ruby apps which bundle the thin
gem will get this web process type:
web: bundle exec thin start -e $RAILS_ENV -p $PORT
Additional process types are declared for Rails 2:
console: bundle exec script/console
and if the app has a jobs:work
rake task:
worker: bundle exec rake jobs:work
Plugin injection in Rails 2
- A Rails stdout plugin is injected.
Rails 3.x applications
Activation
An app is detected as a Rails 3.x app when the Gemfile.lock
file contains a railties
gem, and the gem version is greater than or equal to 3.0.0, and less than 4.0.0. Apps recognized as Rails 3.x apps are denoted with a -----> Ruby/Rails app detected
at deploy-time.
$ git push heroku master
-----> Ruby/Rails app detected
Environment
The following additional environment variables will be set:
RAILS_ENV
=> “production”RACK_ENV
=> “production”
Add-ons
Adds the same add-ons as a “Ruby” app.
Process types
If you don’t include a Procfile
, Rails 3 apps will define a web and console process type at deploy time:
web: bundle exec rails server -p $PORT
console: bundle exec rails console
On Heroku, we recommend Puma as the webserver. Regardless of the webserver you choose, production apps should always specify the webserver explicitly in the Procfile
.
As a special case to assist in migration from Bamboo, Ruby apps which bundle the thin
gem will get this web process type:
web: bundle exec thin start -R config.ru -e $RACK_ENV -p $PORT
Compile phase
As a final task in the compilation phase, the assets:precompile
Rake task is executed. This will compile all assets and put them in your public directory. For more information refer to Rails Asset Pipeline on Heroku.
Plugin injection in Rails 3
- A Rails stdout plugin is injected.
- A static assets plugin is automatically injected.
If you include the rails_12factor
gem, then no plugin injection is performed at all - all the configuration will be made via the gem. You should put this in your :production
group to avoid a bug in development that will cause you to see duplicate logs. This has been fixed in later versions of Rails.
Rails 4.x applications
Activation
An app is detected as a Rails 4.x app when the Gemfile.lock
file contains a railties
gem, and the gem version is greater than or equal to 4.0.0.beta, and less than 5.0.0. Apps recognized as Rails 4.x apps are denoted with a -----> Ruby/Rails app detected
at deploy-time.
$ git push heroku master
-----> Ruby/Rails app detected
Environment
The following additional environment variables will be set:
RAILS_ENV
=> “production”RACK_ENV
=> “production”
Add-ons
Adds the same add-ons as a “Ruby” app.
Process types
If you don’t include a Procfile
, Rails 4 apps will define a web and console process type at deploy time:
web: bundle exec bin/rails server -p $PORT -e $RAILS_ENV
console: bundle exec bin/rails console
On Heroku, we recommend Puma as the webserver. Regardless of the webserver you choose, production apps should always specify the webserver explicitly in the Procfile
.
Compile phase
As a final task in the compilation phase, the assets:precompile
Rake task is executed if you have a assets:precompile
Rake task defined, and don’t have a public/assets/manifest-*.json
file. This will compile all assets and put them in your public directory. If the rake detection or the asset compilation task fails, the deploy will fail as well. For more information refer to Rails Asset Pipeline on Heroku.
Plugin injection in Rails 4
Rails 4 no longer supports plugin functionality, and so Heroku’s support for Rails 4 no longer injects any. However, if you don’t include the rails_12factor
gem, a warning will be raised. This gem replaces the need for the plugins, and ensures that Rails 4 is optimally configured for executing on Heroku.
Rails 5.x applications
Activation
An app is detected as a Rails 5.x app when the Gemfile.lock
file contains a railties
gem, and the gem version is greater than or equal to 5.0.0.beta, and less than 6.0.0. Apps recognized as Rails 5.x apps are denoted with a -----> Ruby/Rails app detected
at deploy-time.
$ git push heroku master
-----> Ruby/Rails app detected
Environment
The following additional environment variables will be set:
RAILS_ENV
=> “production”RACK_ENV
=> “production”RAILS_LOG_TO_STDOUT
=> “enabled”RAILS_SERVE_STATIC_FILES
=> “enabled”
Add-ons
Adds the same add-ons as a “Ruby” app.
Process types
If you don’t include a Procfile
, Rails 5 apps will define a web and console process type at deploy time:
web: bundle exec bin/rails server -p $PORT -e $RAILS_ENV
console: bundle exec bin/rails console
Regardless of the webserver you choose, production apps should always specify the webserver explicitly in the Procfile
.
Compile phase
As a final task in the compilation phase, the assets:precompile
Rake task is executed if you have a assets:precompile
Rake task defined, and don’t have a public/assets/manifest-*.json
file. This will compile all assets and put them in your public directory. If the rake detection or the asset compilation task fails, the deploy will fail as well. For more information refer to Rails Asset Pipeline on Heroku.
Plugin injection in Rails 5
Rails 5 no longer supports plugin functionality, and so Heroku’s support for Rails 5 no longer injects any. Previously in Rails 4, the gem rails_12factor
was required to enable logging and static file service. New applications will now work out of the box. If you are upgrading an application see Rails 5 getting started guide.
Rails 6.x applications
Same as Rails 5.x applications
Rails 7.x applications
Same as Rails 6.x applications
Installed binaries
By default Rails applications that have the execjs
gem or a package.json
file at root will have a default version of Node installed in the application. The version of Node installed by default is:
16.18.1
Applications that have the webpacker
gem or a yarn.lock
file at root will get a default version of Yarn:
1.22.19
If you need a specific version of node for your Ruby application you should use multiple buildpacks to first install node then install Ruby.
$ heroku buildpacks:add heroku/nodejs
$ heroku buildpacks:add heroku/ruby
Verify that your buildpacks are set correctly and that Node comes before Ruby:
$ heroku buildpacks
=== myapp Buildpack URLs
1. heroku/nodejs
2. heroku/ruby
Once you have done this you’ll need a package.json
file in the root of your app. For example to install version 8.9.4
your package.json
could look like this:
{ "engines" : { "node": "8.9.4" } }
You can specify the version of Yarn you want to use in the engines.yarn
key in your package.json
. You will also need a yarn.lock
file checked into your repo. You can get more information on how to configure your Node dependencies on our Node support page.
Commit to git:
$ git add package.json
$ git commit -m 'specify node version'
Now the next time you deploy your Ruby application will use Node version 8.9.4.
Injected plugins
By default, Heroku will inject plugins in Rails 3.x applications to ensure applications get the most out of the Heroku platform. The two plugins that may be injected are documented below. To avoid this injection in Rails 3, include the rails_12factor
gem in your application. In your Gemfile:
gem 'rails_12factor'
Stdout
The rails_stdout_logging
gem ensures that your logs will be sent to standard out.
Heroku treats logs as streams of events, rather than files - by piping logs to stdout, your logs will be captured and consolidated across multiple dynos by Logplex, which in turn makes them available from the command line, $ heroku logs --tail
, or from logging add-ons.
Static assets
The rails3_serve_static_assets
gem lets the web process serve static assets.
In the default Rails development environment assets are served through a middleware called sprockets. In production however most non-heroku Rails deployments will put their ruby server behind reverse HTTP proxy server such as Nginx which can load balance their sites and can serve static files directly. When Nginx sees a request for an asset such as /assets/rails.png
it will grab it from disk at /public/assets/rails.png
and serve it. The Rails server will never even see the request.
On Heroku, Nginx is not needed to run your application. Our routing layer handles load balancing while you scale out horizontally. The caching behavior of Nginx is not needed if your application is serving static assets through an edge caching CDN.
By default Rails 4 will return a 404 if an asset is not handled via an external proxy such as Nginx. While this default behavior will help you debug your Nginx configuration, it makes a default Rails app with assets unusable on Heroku. To fix this we’ve released a gem rails_serve_static_assets
.
This gem, rails_serve_static_assets
, enables your Rails server to deliver your assets instead of returning a 404. You can use this to populate an edge cache CDN, or serve files directly from your web app. This gives your app total control and allows you to do things like redirects, or setting headers in your Ruby code. To enable this behavior in your app we only need to set this one configuration option:
config.serve_static_assets = true
You don’t need to set this option since this that is what this gem does. Now your application can take control of how your assets are served.
Debugger gems fail to install
There are several gems that require very specific patch levels of the Ruby they are running on. This is detrimental to a production app as it locks you into a specific patch level of Ruby and does not allow you to upgrade to receive security fixes.
Heroku releases security patches for Ruby versions as the become available from Ruby core. After we have upgraded a Ruby version, your app will get the new version on next deploy. If your app was using one of these gems you will see a failure when installing gems if we have upgraded the version of Ruby you are using. A failure may look like this:
Installing debugger-linecache
Gem::Installer::ExtensionBuildError: ERROR: Failed to build gem native extension.
Or like this:
Installing debugger
Gem::Installer::ExtensionBuildError: ERROR: Failed to build gem native extension.
The best way to avoid this problem is to not use debugger
or any other debugging gems in production. These gems are designed to hook into the low level components of a language for dynamically stopping and inspecting execution of running code. This is not something you should be doing in production. Instead move these gems to your development
group of the Gemfile
:
group :development do
gem "debugger"
end
Then bundle install
, commit to git, and re-deploy.