Heroku

How It Works

About the Celadon Cedar Stack

Last Updated: 18 January 2012

cedar ruby stack

Table of Contents

Cedar is a runtime stack on Heroku, and is the successor to Bamboo.

Supported Languages and Frameworks

Ruby

Node.js

Clojure

Java

Python

Scala

Stack Software Versions

  • OS: Ubuntu Server 10.04 (Lucid Lynx)
  • Ruby: MRI 1.9.2
  • Bundler: 1.1pre5
  • Node.js: 0.4.7
  • NPM: 1.0.6
  • JVM: OpenJDK 6

Using Cedar

To create an app on the Cedar stack, use the --stack argument:

$ heroku create --stack cedar

Make sure you’re running version 2.1.0 or higher of the Heroku command-line tool to access the run and scale commands:

$ heroku update

Differences Between Bamboo and Cedar

Procfile for flexible process types

Cedar introduces a new way to think about scaling your app: the process model. This is a natural extension of the dynos/workers model available on the Bamboo stack, but generalized to allow you to use your own custom list of process types, specified in a Procfile.

This covers use cases such as running Resque instead of Delayed Job, using a clock process like resque-scheduler or clockwork, and using a webserver other than Thin (such as Goliath).

Read more about developing apps with Procfile and Foreman, and deploying to Heroku/Cedar.

One-off processes for rake and console

On Bamboo, heroku rake and heroku console were implemented as special-cased execution paths, with output delivered over HTTP. This approach has a number of weaknesses, such as timeouts and non-interactivity on rake tasks.

Cedar uses the heroku run command to launch one-off processes like rake and the irb attached to your terminal via a TCP character connection. For example, using it to run rake commands:

$ heroku run rake db:migrate
Running `rake db:migrate` attached to terminal... up, ps.1
(in /app)
Migrating to CreateWidgets (20110204210157)
==  CreateWidgets: migrating ==================================================
-- create_table(:widgets)
   -> 0.0120s
==  CreateWidgets: migrated (0.0121s) =========================================

And for an interactive console to your Rails app:

$ heroku run console
Running `console` attached to terminal... up, ps.2
Loading production environment (Rails 3.0.3)
irb(main):001:0>

The console is a standard irb shell (invoked via rails console), fully isolated from your web dyno.

New HTTP stack (herokuapp.com)

On Cedar, an app named foo will have the default hostname of foo.herokuapp.com (instead of foo.heroku.com).

The herokuapp.com domain routes to a new HTTP stack which offers a much more direct routing path to your web processes. This allows for advanced HTTP uses such as chunked responses, long polling, and using an async webserver to handle multiple responses from a single web process. It does not include Varnish as a reverse proxy cache.

Read more about the new HTTP stack.

Code injection

The Aspen and Bamboo stacks both do a substantial amount of code injection, both at slug compile time and at runtime, to make your app “just work” on Heroku. While this is part of the “Heroku magic,” the downside to this is that code injection results in mysterious, hard-to-diagnose side-effects that can be extremely frustrating, or even prevent certain types of apps from running completely.

Cedar strives for purism: the code running in your local environment is as close as possible to what runs when deployed on Heroku. This solves a great deal of deployment and debugging pain.

The downside to less code injection is that in some places there will be slightly more configuration necessary. Some examples of this include needing to specify the pg gem in your Gemfile if you’re using the Heroku PostgreSQL database, and likewise with the newrelic_rpm gem if you’re using the New Relic add-on. This is a difficult trade-off, but it will save you debugging headaches in the long run, particularly for larger and more sophisticated applications.

When we do inject code, we do it at compile time; and call it out with a message so that you can inspect what code is being added to your app, should you desire. One example of this is rails_log_stdout, a plugin injected into Rails apps to cause their logs to go to stdout, as is required for routing logs into the logging system.

PostgreSQL gem

You must specify the pg gem in your Gemfile in order to use the shared or dedicated Heroku PostgreSQL database:

gem 'pg'

We highly recommend running Postgres in your development environment, to remove the chance for differences between SQLite or MySQL and Postgres from causing issues in your production environment. (Postgres is extremely easy to install locally with Homebrew, apt-get, or the Postgres one-click installer for Windows.)

However, if you prefer to only use the pg gem in your deployed app, you can wrap it in the production group:

group :production do
  gem 'pg'
end

Your database credentials will still be configured automatically: at slug compile time, a config/database.yml that parse the DATABASE_URL from the environment will be written into your app.

Ruby webserver (Webrick vs Thin)

Because Cedar doesn’t inject any gem dependencies into your app, a vanilla Rails app will run on Webrick (the built-in webserver in the Ruby standard library). We highly recommend Thin for all apps. To use Thin, add it to your Gemfile:

gem 'thin'

and define it as a web process in your Procfile:

web: bundle exec thin start -p $PORT

Similar to the pg gem above, you can chose to put this only in your production gem group if you wish, but we recommend you use Thin in local development too.

Adding a database

A Heroku shared PostgreSQL database (shared-database:5mb) will be automatically added to your app in any of the following cases:

  • The app is a Rails application
  • The pg gem is specified in the Gemfile

This detection and installation will happen only on the first push of your app. If you’d like to later add the free shared database manually, you can do so with:

$ heroku addons:add shared-database:5mb

Migrating From Bamboo to Cedar

Before migrating to Bamboo, you should make sure your app runs on Ruby 1.9.2. If your app is not already deployed successfully to bamboo-mri-1.9.2, you should do that first, and then come back and try Cedar.

Once you’re sure your app is fully compatible with Ruby 1.9.2, create an app on the Cedar stack and push to it. Currently, stack:migrate does not work for moving apps to Cedar.