Ruby Database Provisioning
Last updated November 15, 2017
Table of Contents
Due to how the buildpack release API currently functions, Heroku’s Ruby support (implemented by the Ruby buildpack) can only add an add-on to an application on the first deploy.
By default, the lowest, free Heroku Postgres plan will be added to any Ruby app that has the pg
gem dependency, when deployed for the first time.
Since the default of Rails applications is to come bundled with sqlite3
instead of pg
and since the add-on can only be added automatically on the first push, many developers were deploying their code, realizing that they were using the wrong database driver, and then updating their Gemfile.
If they accidentally get a successful deploy in this process without the pg
gem, then the buildpack would never be able to automatically provision Heroku Postgres on subsequent deploys.
For backwards compatibility with previous stacks on Heroku, it was decided that all apps that deploy with the Rails (more specifically the railties
gem) will get a database by default. This prevents the situation of when you’ve deployed before putting pg
in your Gemfile, but add it in later.
Using a different database with Rails
If you are using a different database to Heroku Postgres, the default behavior of provisioning a Postgres database for Rails apps may conflict with your configuration. For detailed information about how exactly your version of Rails connects to the database please see Rails database connection behavior.
With all versions of Rails on Heroku, any information present in the DATABASE_URL
environment variable will take precedence by default. This is a problem when you are not using a Postgresql database, because after Heroku adds one to your application it will “promote” it to DATABASE_URL
if there is no environment variable already set. When this happens your application will try to connect to the Postgresql database by accident.
There are two strategies for dealing with this case - setting the DATABASE_URL
config var, or removing it.
Setting the DATABASE_URL
config var
You can set a DATABASE_URL
config var on your app. This will prevent Heroku from “promoting” the Postgres database add-on:
$ heroku config:set DATABASE_URL=<scheme>://<username>:<password>@<host>
Here, you would replace the above values with the credentials and address for your database.
If you’re using pipelines or review apps, this strategy won’t work since you won’t have the ability to heroku config:set
before you deploy each review app.
To remedy this you can dynamically assign the value of DATABASE_URL
inside of your code. This must be done before the database is initialized. For example:
ENV["DATABASE_URL"] = "mysql://#{ ENV['MY_DATABASE_PASSWORD'] }:#{ ENV['MY_DATABASE_USERNAME'] }@#{ ENV['MY_DATABASE_HOST'] }"
You can place this in an initializer, or directly in your config/database.yml
inside of an ERB code section. The important thing is that this code is run before your application attempts to connect to the database.
Deleting the DATABASE_URL
config var
Alternatively if your production database credentials are in your config/database.yml
you can ensure that your app does not use DATABASE_URL
to connect to the database by deleting it before the connection gets initialized.
ENV.delete("DATABASE_URL")