3 min read
Next in trending

Zero downtime re-deploys

How to update your Node.js application without disrupting service for your users.

Zero downtime re-deploys

How to update your Node.js application without disrupting service for your users.


Problem

After deploying your application, one of the very next things you’ll want to do is redeploy it. Perhaps because of a bug, a new feature, or both! What’s the difference? In any case, there’s always a reason to re-deploy. And because it’s likely to happen frequently it shouldn’t waste your time or piss off your users.

A pipe tool.

Solution

liveswap is a library that helps you update an application’s code without stopping it. It also ships with a command-line tool and it doesn’t impose any special requirements or conventions on your application code.

It works by creating a light-weight master process that runs your application code as worker processes. It then starts listening for instructions.

When you send an upgrade instruction, workers take turns disconnecting their underlying servers. When a server is disconnected, it lets the old connections finish up, but no new connections are accepted. When all of the worker’s connections have been closed, it will be retired and a new one will be created using the new code.

Example

Take for instance a trivial http server…

http.createServer(function (req, res) {
 res.writeHead(200, {'Content-Type': 'text/plain'})
res.end('Hello World\n')
}).listen(1337, '127.0.0.1')

Start the application…

We can specify the path to the code and some other options, like how many forks we want!

liveswap --start index.js --forks 16

After the program has been started, we edit the file…

http.createServer(function (req, res) {

res.writeHead(404, {‘Content-Type’: ‘text/plain’})
res.end(‘Not Found\n’)
}).listen(1337, ‘127.0.0.1')

But wait! Don’t restart, upgrade…

Tell the existing process to upgrade to the new code…

liveswap —-upgrade index.js

If you try the above code, be sure the browser’s connection actually gets closed.

Pre-upgrade procedures

Before you upgrade, you will likely want to pull from a git repo (or something similar), in which case you can use the pre-upgrade option. This option specifies a file with a module that exports a function. The function is called prior to the upgrade. Here is an example of a pre-upgrade module…

var exec = require('child_process').exec
var path = require('path')

module.exports = function(target, done) {
  var cmd = 'git pull origin master'
var opts = {
cwd: path.dirname(target)
}
  exec(cmd, opts, function(err, stdout, stderr) {
console.log(stdout)
console.log(stderr)
done(err || null);
})
}

The option can be specified from the command line. This helps automate the work of updating the code before restarting the workers.

liveswap —-start ./index.js —-pre-upgrade ./pull.js

Also, our simple node module provides the opportunity to handle different failure scenarios. Git pull didn’t work? No problem, try something else.

More use cases and ideas

This is useful if you have a web app that has long lived connections (like web sockets) or if you are building systems services that require high availability.

Large re-deployments…

The address that liveswap operates on can be modified so that it is available inside your local area network. If you need to perform an update across many servers, all you need is a small udp or tcp program that contacts all your servers and sends the proper JSON values.

This is not…

This is not a process monitoring solution. Some naive process monitors think that if you infinitely restart an application, everything will eventually be ok. You should be using a mature, well thought out processes monitoring solution like SMF!

Conclusion

Download the source, fork it, star it, and if you find bugs or have idas, open issues here. Install it with npm and have fun!

npm install liveswap -g