The New Heroku (Part 2 of 4): Node.js & New HTTP Capabilities

Listen to this article

Node.js has gotten its share of press in the past year, achieving a level of attention some might call hype. Among its touted benefits are performance, high concurrency via a single-threaded event loop, and a parity between client-side and sever-side programming languages which offers the Promethean opportunity of making server-side programming accessible to front-end developers.

But what is Node.js, exactly? It's not a programming language - it's simply Javascript. It's not a VM: it uses the V8 Javascript engine, the same one used by the Chrome web browser. Nor is it simply a set of libraries for Javascript. Nor is it a web framework, though the way it is sweeping the early-adopter developer community is reminiscent of Rails circa 2005.

Most would cite Node's asynchronous programming model, driven by the reactor pattern, as its key differentiator from other ways of writing server-side code for the web. But even this is not new or unique: Twisted for Python has been around for a decade.

So what makes Node special?

One part of the reason Node.js has captured the hearts and minds of alpha geeks in web development is because it offers all the things described above - a language, a fast and robust VM, a set of compatible and well-documented libraries, and an async framework - all bundled together into a single, coherent package.

The charismatic leadership of Ryan Dahl may be another part of the answer: strong figureheads are often key elements in driving explosive developer community growth (see: Linux/Linus Torvalds, Rails/David Heinemeier Hansson, Ruby/Matz, Python/Guido van Rossum, Redis/Salvatore Sanfilippo, CouchDB/Damien Katz).

But the primary reason is even simpler: Node.js is the right technology at the right time. Demand for asynchronous capabilities in web apps is being driven by what has become known as "the realtime web." Another label for "realtime" (which has a conflicting definition from computer science) is "evented."

The evented web means users getting updates pushed to them as new data becomes available, rather than having to poll for it. Polling is the software equivalent of nagging - not fun or efficient for either end of the transaction.

The rise of an event-driven web makes the appearance of Node.js timely, because Node.js has evented baked in at a level that no other programming language or framework can match. And Node.js being Javascript - a language born of the web - closes the deal.

Unix daemons (such as the famously-fast Nginx) often use evented programming to maximize concurrency and robustness. The seminal C10K article explores the use of system calls such as kqueue and epoll for evented programming. In scripting languages, evented frameworks such as Twisted for Python and EventMachine for Ruby enjoy popularity.

EventMachine is a fascinating case study to compare against Node.js. Because EventMachine's reactor takes over the entire execution thread (via EM.run ), most vanilla Ruby programs require a rewrite to use it, and the developer is cut off from the vast collection of synchronous libraries found in the Ruby ecosystem. A whole slew of em-* libraries have appeared, effectively creating a sub-language of Ruby. The partial incompatibility between Ruby and em-Ruby is a source of confusion for developers new to evented programming.

This is where Node.js succeeds: pulling together the language, the async framework, and a whole universe of libraries guaranteed to work in the evented model.

Heroku's new runtime stack, Celadon Cedar, includes first-class support for Node.js apps. A quick taste:

var app = require('express').createServer(); app.get('/', function(request, response) { response.send('Hello World!'); }); app.listen(process.env.PORT || 3000);

NPM has become the community standard for dependency management in Node.js. Writing a package.json declares your app's dependencies and tells Heroku your app is a Node.js app:

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

Read the full Node.js on Heroku/Cedar quickstart guide to dive in and try it for yourself.

Because the fate of Node.js is entwined so directly with that of the next-generation HTTP techniques (such as chunked responses and long polling), Cedar comes bundled with a new HTTP stack. The new HTTP stack, which runs on the herokuapp.com domain, provides a more direct connection between the end user's browser (or other HTTP client) and the app dyno which is serving the request.

Here are two examples of apps which use advanced HTTP features for evented apps:

Ryan Dahl's chat server: sample deploy on Cedar and sourcecode.

The Node.js Knockout 2011 homepage: sample deploy Cedar and sourcecode. (Click anywhere with the mouse or use arrow keys to move your avatar around. Try opening it in two browser windows side-by-side to see how moving the avatar in one window updates the other one in real time!)

One caveat: we've made the difficult decision to hold off on supporting WebSockets, as the protocol is still in flux and not uniformly supported in modern standards-compliant browsers. Once the WebSockets protocol matures further, we'll be delighted to support it in the herokuapp.com HTTP stack. In the meantime, use the Socket.IO library, which falls back to the best available transport mechanism given the HTTP stack and browser capabilities for a given HTTP request.

Node.js is still under rapid development, and staying abreast of new releases can be a challenge. Heroku must balance the goals of being a curated, erosion-resistant platform against keeping pace with extremely active developer communities such as Ruby, Ruby/Rails, and Node.js. We look forward to applying all we've learned so far to the highly dynamic world of Node.js.