Heroku Deployments

I’ve been doing a rewrite of Lettra in Rails 8 and taking note of the deployment process to Heroku1.

Start App and Create Database

$ rails new lettra --database=postgresql
$ bin/rails db:create

Create Welcome Page

$ rails g controller welcome

Create app/views/welcome/index.html.erb and add a “Hello, World” message:

<h1>Hello, World!</h1>
<p>The time is now: <time><%= Time.now %></time></p>

I’m using Time.now as a bit of a sanity check because Heroku won’t be using our local PST timezone by default.

To make this page the root page for the app, we update the config/routes.rb file with:

root "welcome#index"

At this point we should be able to see the app on port 3000 by running rails s in the CLI.

Specify Ruby Version

I’m currently on Ruby 3.3.4. Newest version as of time of writing is 3.3.7, but no need to be on the cutting edge just yet since Rails 8 was released in mid-December and it supports anything past version 3.3.

So we add the desired Ruby version in the Gemfile and run $ bundle update --ruby. We can then verify the change was successful by running $ cat Gemfile.lock | grep RUBY -a1

Create Procfile

The Procfile explicitly declares what command to execute to start the app. I’m using the Puma web server since it’s fast, tested, and has support for Rack middleware.

In the root directory we create the Procfile and add this to the file:

web: bundle exec puma -C config/puma.rb

Git

Add all and commit changes to repo.

Create a Heroku App

From CLI in app’s root directory:

$ heroku apps:create

This creates a $7/mo “web” Dyno.

Provision Heroku Database

Note from Heroku:

A mini Postgres size costs $5 a month, prorated to the minute.

$ heroku addons:create heroku-postgresql:essential-0

Environment Variables

Update: While this wasn’t an issue for the inital deployment, Heroku throws an error when attempting to run subsequent migrations on the production database with the default Rails configuration.

Heroku will throw the following error: ActiveRecord::ConnectionNotEstablished error when running rails db:migrate on Heroku.

It’ll look something like this:

ActiveRecord::ConnectionNotEstablished: connection to server on socket "/var/run/postgresql/.s.PGSQL.5432" failed

It’s an easy fix though, we can provide access to the Heroku database ENV variable by updating the config/database.yml.

production:
  primary: &primary_production
    <<: *default
    url: <%= ENV['DATABASE_URL'] %>
  cache:
    <<: *primary_production
    database: lettra_production_cache
    migrations_paths: db/cache_migrate
  queue:
    <<: *primary_production
    database: lettra_production_queue
    migrations_paths: db/queue_migrate
  cable:
    <<: *primary_production
    database: lettra_production_cable
    migrations_paths: db/cable_migrate

That’s all!

Deploy to Heroku

$ git push heroku main

After a successful deployment, complete these tasks as necessary:

  • Database migrations
  • Scale dynos (not needed yet)
  • Check app’s logs if issues arise

Migrate Heroku Database

$ heroku run rake db:migrate

Fix Timezone to PST from GMT

$ heroku config add: TZ="America/Los_Angeles"

Open App in Browser

$ heroku open

View App Logs

$ heroku logs

By appending the -t / --tail flag, we can see a full, live stream of the app’s logs:

$ heroku logs --tail

At this point, the starting cost for a Rails app with a Heroku backend will be max around $12.00 / month. The provision for the database is always the most expensive part of it, since not using the app does bring the cost down on the web dyno front.

  1. Since deploying to production will be the main focus of this devlog, I’m referencing this article from the Heroku Dev Center.