Rails on Heroku

The official guide is a great place to start, but there’s more you can do to make life easier.

tangerine Based on lessons learned in the early days of Instacart

Deploys

For zero downtime deploys, enable preboot. This will cause deploys to take a few minutes longer to go live, but it’s better than impacting your users.

heroku features:enable -a appname preboot

Add a preload check make sure your app boots. Create lib/tasks/preload.rake with:

task preload: :environment do
  Rails.application.eager_load!
  ::Rails::Engine.subclasses.map(&:instance).each { |engine| engine.eager_load! }
  ActiveRecord::Base.descendants
end

And add a release phase task to your Procfile to run the preload script and (optionally) migrations.

release: bundle exec rails preload db:migrate

Create a deployment script in bin/deploy. Here’s an example:

#!/usr/bin/env bash

function notify() {
  # add your chat service
  echo $1
}

notify "Deploying"

git checkout master -q && git pull origin master -q && \
git push origin master -q && git push heroku master

if [ $? -eq 0 ]; then
  notify "Deploy complete"
else
  notify "Deploy failed"
fi

Be sure to chmod +x bin/deploy. Replace the echo command with a call to your chat service (Hipchat instructions).

Deploy with:

bin/deploy

Migrations

Follow best practices for zero downtime migrations.

If you start to see errors about prepared statements after running migrations, disable them.

production:
  prepared_statements: false

Don’t worry! Your app will still be fast (and you’ll probably do this anyways at scale since PgBouncer requires it).

Rollbacks

Create a rollback script in bin/rollback.

#!/usr/bin/env bash

function notify() {
  # add your chat service
  echo $1
}

notify "Rolling back"

heroku rollback

if [ $? -eq 0 ]; then
  notify "Rollback complete"
else
  notify "Rollback failed"
fi

Don’t forget to chmod +x bin/rollback. Rollback with:

bin/rollback

Logs

Add Papertrail to make your logs easily searchable.

heroku addons:create papertrail

Set it up to archive logs to S3.

Performance

Add a performance monitoring service like New Relic.

heroku addons:create newrelic

And follow the installation instructions.

Use a CDN like Amazon CloudFront to serve assets.

Autoscaling

Check out HireFire.

Productivity

Use Archer to enable console history.

Use aliases for less typing.

alias hc="heroku run rails console"

Staging

Create a separate app for staging.

heroku create staging-appname -r staging
heroku config:set RAILS_ENV=staging RACK_ENV=staging -r staging

Deploy with:

git push staging branch:master

You may also want to password protect your staging environment.

class ApplicationController < ActionController::Base
  http_basic_authenticate_with name: "happy", password: "carrots" if Rails.env.staging?
end

Lastly...

Have suggestions? Please share. For more tips, check out Production Rails.

hatched_chick Happy coding!

Published August 12, 2015 · Tweet


You might also enjoy

Dokku on DigitalOcean

Scaling the Monolith

Gem Patterns


All code examples are public domain.
Use them however you’d like (licensed under CC0).