logo

Running node.js in production

I started my first node.js project in late 2013, working with this tech stack is an enjoyable experience but there were a couple very basic practices which weren't clear to me initially. Once we started using clustering to automatically restart the node process after errors and managed the process with upstart scripts we had a stable system which allowed this project to be successful.

if (cluster.isMaster) {  
  cluster.fork();

  cluster.on('disconnect', function(worker) {
    console.error('disconnect!');
    cluster.fork();
  });

} else {

  var app = express();
  // do rest of express setup here

  app.use(function domainMiddleware(req, res, next) {

    var reqDomain = domain.create();

    reqDomain.on('error', function (err) {
      console.error('error', err.stack);
      try {
        // make sure we close down within 30 seconds
        var killtimer = setTimeout(function() {
          process.exit(1);
        }, 30000);
        // But don't keep the process open just for that!
        killtimer.unref();
        // Let the master know we're dead.  This will trigger a
        // 'disconnect' in the cluster master, and then it will fork
        // a new worker.
        cluster.worker.disconnect();
        // try to send an error to the request that triggered the problem
        res.statusCode = 500;
        res.setHeader('content-type', 'text/plain');
        res.end('Oops, there was a problem!\n');
      } catch (er2) {
        console.error('Error sending 500!', er2.stack);
      }
    });

    reqDomain.run(next);
  });

  app.listen(port, function(){
    console.log('node listening on port '+port);
  });
  module.exports = app;    

This process is described in the official node docs

# firefly.conf

description "some website"

start on started networking  
stop on runlevel [016]

limit nofile 1000000 1000000

console log

script

  mkdir -p /home/webdev/web_server
  cd /home/webdev/web_server

  npm run production
end script

respawn  

The first node.js project I put into production was replacing the Rails frontend of wordnik.com. This project helped speed up the site while reducing hosting costs. More details are on the Reverb Developers Blog Running off the Rails: Tackling Technical Debt with a Switch to Node.js

While I moved on from Reverb in late 2014 I am still happy to support Wordnik which recently spun off into a non profit. I adopted a word as soon as the program was announced: