Heroku

How It Works

Getting Started with Node.js on Heroku/Cedar

Last Updated: 21 December 2011

cedar node-js

Table of Contents

This quickstart will get you going with Node.js and the Express web framework on the Cedar stack.

Prerequisites

  • Basic Node.js knowledge, including an installed version of Node.js and NPM.
  • Your application must run on Node.js 0.4.7.
  • Your application must use NPM to manage dependencies.
  • A Heroku user account. Signup is free and instant.

Local Workstation Setup

We’ll start by setting up your local workstation with the Heroku command-line client and the Git revision control system; and then logging into Heroku to upload your ssh public key. If you’ve used Heroku before and already have a working local setup, skip to the next section.

If you have... Install with...
Mac OS X Download OS X package
Windows Download Windows .exe installer
Ubuntu Linux apt-get repository
Other Tarball (add contents to your $PATH)

Once installed, you’ll have access to the heroku command from your command shell. Log in using the email address and password you used when creating your Heroku account:

$ heroku login
Enter your Heroku credentials.
Email: adam@example.com
Password: 
Could not find an existing public key.
Would you like to generate one? [Yn] 
Generating new SSH public key.
Uploading ssh public key /Users/adam/.ssh/id_rsa.pub

Press enter at the prompt to upload your existing ssh key or create a new one, used for pushing code later on.

Write Your App

You may be starting from an existing app. If not, here’s a simple “hello, world” sourcefile you can use:

web.js

var express = require('express');

var app = express.createServer(express.logger());

app.get('/', function(request, response) {
  response.send('Hello World!');
});

var port = process.env.PORT || 3000;
app.listen(port, function() {
  console.log("Listening on " + port);
});

Declare Dependencies With NPM

Cedar recognizes an app as Node.js by the existence of a package.json. Even if your app has no dependencies, you should still create a package.json that declares a name, version, and empty dependencies in order that it appear as a Node app.

Here’s an example package.json for the Express app we created above:

package.json

{
  "name": "node-example",
  "version": "0.0.1",
  "dependencies": {
    "express": "2.2.0"
  }
}

Run npm install to install your dependencies locally.

You’ll also want to prevent NPM installed packages from going into revision control with this file:

.gitignore

node_modules

Make sure that all of your app’s dependencies are declared in package.json and that you are not relying on any system-level packages.

Declare Process Types With Foreman/Procfile

To run your web process, you need to declare what command to use. In this case, we simply need to execute our Node script. We’ll use Procfile to declare how our web process type is run.

Here’s a Procfile for the sample app we’ve been working on:

web: node web.js

Now that you have a Procfile, you can start your application with Foreman:

$ foreman start
14:39:04 web.1     | started with pid 24384
14:39:04 web.1     | Listening on 5000

Your app will come up on port 5000. Test that it’s working with curl or a web browser, then Ctrl-C to exit.

Deploy to Heroku/Cedar

We now have the three major components of our app: dependencies in package.json, process types in Procfile, and our application source in web.js. Let’s put it into Git:

$ git init
$ git add .
$ git commit -m "init"

Create the app on the Cedar stack:

$ heroku create --stack cedar
Creating sharp-rain-871... done, stack is cedar
http://sharp-rain-871.herokuapp.com/ | git@heroku.com:sharp-rain-871.git
Git remote heroku added

Deploy your code:

$ git push heroku master
Counting objects: 9, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (7/7), done.
Writing objects: 100% (9/9), 923 bytes, done.
Total 9 (delta 2), reused 0 (delta 0)

-----> Heroku receiving push
-----> Updating alpha language packs... done
-----> Node.js app detected
-----> Vendoring node 0.4.7
-----> Installing dependencies with npm 1.0.8
       express@2.1.0 ./node_modules/express 
       ├── mime@1.2.2
       ├── qs@0.3.1
       └── connect@1.6.2
       Dependencies installed
-----> Discovering process types
       Procfile declares types -> web
-----> Compiled slug size is 3.2MB
-----> Launching... done, v2
       http://sharp-rain-871.herokuapp.com deployed to Heroku

To git@heroku.com:sharp-rain-871.git
 * [new branch]      master -> master

Before looking at the app on the web, we’ll need to scale the web process:

$ heroku ps:scale web=1
Scaling web processes... done, now running 1

Now, let’s check the state of the app’s processes:

$ heroku ps
Process       State               Command
------------  ------------------  --------------------------------------------
web.1         up for 10s          node web.js

The web process is up. Review the logs for more information:

$ heroku logs
2011-03-10T10:22:30-08:00 heroku[web.1]: State changed from created to starting
2011-03-10T10:22:32-08:00 heroku[web.1]: Running process with command: `node web.js`
2011-03-10T10:22:33-08:00 heroku[web.1]: Listening on 18320
2011-03-10T10:22:34-08:00 heroku[web.1]: State changed from starting to up

Looks good. We can now visit the app with heroku open.

Setting NODE_ENV

The Express framework uses the NODE_ENV environment variable to determine some behaviors related to caching. If you’re using Express, set a config var with this value:

$ heroku config:add NODE_ENV=production
Adding config vars:
  NODE_ENV => production
Restarting app... done, v3.

Console

Cedar allows you to launch a REPL process attached to your local terminal for experimenting in your app’s environment:

$ heroku run node
Running `node` attached to terminal... up, ps.1
>

This console has nothing loaded other than the Node.js standard library. From here you can require some of your application files.

Advanced HTTP Features

The WebSockets protocol is still in changing rapidly and is not yet supported on the Cedar stack.

The HTTP stack available to Cedar apps on the herokuapp.com subdomain supports HTTP 1.1, long polling, and chunked responses. Ryan Dahl’s chat example is deployed on Heroku here as a long-polling example.

Running a Worker

The Procfile format lets you run any number of different process types. For example, let’s say you wanted a worker process to complement your web process:

Procfile

web: node web.js
worker: node worker.js

Running more than one dyno for an extended period may incur charges to your account. Read more about dyno-hour costs.

Push this change to Heroku, then launch a worker:

$ heroku ps:scale worker=1
Scaling worker processes... done, now running 1

Using a Postgres Database

To add the free, shared 5MB PostgreSQL database to your app, run this command:

$ heroku addons:add shared-database

This sets the DATABASE_URL environment variable. Add the postgres NPM module to your dependencies:

"dependencies": {
  ...
  "pg": "0.5.4",
  "express": "latest"
}

And use the module to connect to DATABASE_URL from somewhere in your code:

var pg = require('pg');

pg.connect(process.env.DATABASE_URL, function(err, client) {
  var query = client.query('SELECT * FROM your_table');

  query.on('row', function(row) {
    console.log(JSON.stringify(row));
  });
});

Read more about the Heroku PostgreSQL database.

Using Redis

To add a Redis database to your app, run this command:

$ heroku addons:add redistogo

This sets the REDISTOGO_URL environment variable. Add the redis-url NPM module to your dependencies:

"dependencies": {
  ...
  "redis-url": "0.0.1"
}

And use the module to connect to REDISTOGO_URL from somewhere in your code:

var redis = require('redis-url').connect(process.env.REDISTOGO_URL);

redis.set('foo', 'bar');

redis.get('foo', function(err, value) {
  console.log('foo is: ' + value);
});

Troubleshooting

If you push up your app and it crashes (heroku ps shows state crashed), check your logs to find out what went wrong. Here are some common problems.

Exact version of Node.js

Node changes substantially between versions. Cedar users Node.js v0.4.7, so make absolutely sure you develop your app locally with this version.

Missing a dependency

If your app crashes due to missing a dependency, you may have it installed locally but not specified in your package.json.