I really like the pg PostgreSQL library by Brian Carlson, and considering the amount of attention we’ve given to Redis and MongoDB on DailyJS I thought it was time to give relational databases some coverage again.
Heroku is one of many services that supports Node. This tutorial will demonstrate how easy it is to get a simple Express and pg app running.
This tutorial is based on the following documentation:
- Getting Started With Node.js on Heroku/Cedar
- Heroku Database FAQ
- pg’s Documentation
- pg’s Example App
The files for this tutorial can be found here: alexyoung / dailyjs-heroku-postgres.
Getting Started
An account at Heroku is required first. Next, install the Heroku client:
- Heroku for Mac OS X
- Heroku for Windows
- Ubuntu Heroku installation instructions
- For other operating systems, use the Heroku client tarball
Once that’s installed, try typing heroku help
in a terminal to see what the command-client client can do. Heroku obviously realised that us developers prefer using the command-line to a GUI — although some basic management features are available through Heroku’s web interface, almost everything is handled from the command-line tool.
Authentication is requried before progressing:
heroku login
I had to tell Heroku about my public SSH key too:
heroku keys:add ~/.ssh/id_rsa.pub
Module Installation
Heroku wisely supports npm
, so our app begins with a package.json
:
{
"name": "dailyjs-heroku-postgres"
, "version": "0.0.1"
, "dependencies": {
"express": "2.4.5"
, "pg": "0.5.7"
}
}
PostgreSQL Setup
Heroku uses environmental variables to supply database connection parameters. This is simply process.env.DATABASE_URL
for PostgreSQL. Connecting to the database is as simple as this:
var pg = require('pg').native
, connectionString = process.env.DATABASE_URL || 'postgres://localhost:5432/dailyjs'
, client
, query;
client = new pg.Client(connectionString);
client.connect();
query = client.query('SELECT * FROM mytable');
query.on('end', function() { client.end(); });
Notice how pg
uses events — I’ve called client.end()
so this script will exit gracefully when it’s finished. If you’ve got PostgreSQL installed locally you could try experimenting with this script.
Schema
There’s a few ways to change the database schema on Heroku. I’ve made a little schema creation script:
var pg = require('pg').native
, connectionString = process.env.DATABASE_URL || 'postgres://localhost:5432/dailyjs'
, client
, query;
client = new pg.Client(connectionString);
client.connect();
query = client.query('CREATE TABLE visits (date date)');
query.on('end', function() { client.end(); });
I’ll explain how to run this on Heroku later.
Another option would be to use a library like node-migrate by TJ Holowaychuk. I haven’t actually used this before, but it seems like a sensible way to keep local schemas in sync as developers work on a project.
Typing heroku help pg
shows the commands available for PostgreSQL, and this includes heroku pg:psql
which can be used to open a remote connection to a dedicated database. This won’t be allowed for a shared database, but could be used to modify the schema.
Example App
Now we’ve got a package.json
, we just need an app to run. Create a file called web.js
that starts like this:
var express = require('express')
, app = express.createServer(express.logger())
, pg = require('pg').native
, connectionString = process.env.DATABASE_URL || 'postgres://localhost:5432/dailyjs'
, start = new Date()
, port = process.env.PORT || 3000
, client;
Notice how I use Heroku’s environmental variable for the database connection string and server port, or defaults for development purposes.
Now we can add the code required to connect to the database:
client = new pg.Client(connectionString);
client.connect();
A single Express route should suffice for this tutorial:
app.get('/', function(req, res) {
var date = new Date();
client.query('INSERT INTO visits(date) VALUES($1)', [date]);
query = client.query('SELECT COUNT(date) AS count FROM visits WHERE date = $1', [date]);
query.on('row', function(result) {
console.log(result);
if (!result) {
return res.send('No data found');
} else {
res.send('Visits today: ' + result.count);
}
});
});
And we better start the app too:
app.listen(port, function() {
console.log('Listening on:', port);
});
Procfile
The last thing we need is a file that tells Heroku what our main script is called. Create a file called Procfile
:
web: node web.js
Deploying
Heroku uses Git for deployment, so set up a repo:
git init
git add .
git commit -m 'First commit'
Then run this command which creates a remote app on the service with a random name:
heroku create --stack cedar
It’ll give you the URL, but your app isn’t quite ready yet.
Now push
the repo to make the magic happen:
git push heroku master
And tell Heroku you want to use a database:
heroku addons:add shared-database
And finally… run the schema creation script:
heroku run node schema.js
Hopefully you now have a little Node and PostgreSQL app running on Heroku!
If anything went wrong, Heroku’s documentation is excellent, and you can download my sample source here: alexyoung / dailyjs-heroku-postgres.