I love node, but I’ve run into several gotchas with node in production the last few years. Here are the top 6.
1. The website (server process) is fragile. With node, the process restarts on every unhandled exception. This is different from Ruby on Rails, where you have a separate server process like Unicorn, or PHP where it runs as an Apache module.
With one client that was transitioning from PHP to node, our first deployments felt like we were “plugging the dike” – there were so many server crashes. Until we stabilized things, this sort of gave node a bad name (the perception was that PHP was more stable – but in fact the exceptions were just hidden).
Handling all potential errors, as well as unplanned exceptions is impossible. Most deployments have another process to restart the primary node server process when it bombs. If you’re using a PAAS provider, this will be provided for you, but if you want fine grain control of your server (most web application companies will), hosting and scaling (keeping processes up and enough process around) is a challenge.
Common server-restarting libraries for node are: Upstart, Forever, or God.
2. Writing and maintaining asynchronous code. Callbacks are a simple mechanism starting out, but as your server code grows in complexity, they become a hairball. Crazy callback chains (AKA “callback hell”) make code unreadable. Even simple code that could’ve been procedural is forced to use callbacks due to the libraries you’re using.
Mixing synchronous and asynchronous code makes it difficult to handle every error. Furthermore, you have to understand the event loop to know when execution actually switches contexts. As you’re running your code – if you forget to call a callback, you’ll be left waiting to find out what happened. And, asynchronicity makes even your tests become more complicated.
The Async library exists to handle common asynchronous patterns. Personally, I prefer the “promise” (or “deferred”) pattern. It seems like a hack to send a function as a parameter, instead the promise pattern returns an object representing the state of the asynchronous call instead. jQuery has a promise library for the client side. When is the promise library we selected for a recent node-based web site (comprehensive API and more standards based).
3. Too much choice. The flip side of all those great NPM packages is that there is no clear winning web framework (think Ruby on Rails) for node – in fact, there are several competing server side frameworks (express, hapi, sails, kraken). Each with their own conventions for:
a) File structure
b) Deploying code
c) Building assets
d) Automated testing
And of course, the best choices for each of these changes monthly. This, combined with #2 is why Node is not yet a great choice for simple human facing web sites.
Visualization of NPM Packages
Thanks to Scott Nonnenberg, author of thehelp-cluster (a solution to #1) for feedback on this post.
Please leave a comment and tell me: what problems are you having with Node.js?