Getting your Node.js app production ready

Practical guide

@naugtur, Code Europe 2016

## What's this node thing good for? * translation layers * websockets on top of heavy services * middlewares * integrations * microservice architectures
## How does it work? * event loop * all asynchronous * no concurent memory access
## Why write JavaScript? * You all know some of it by now * Still kinda mandatory for web apps * It's everywhere * Decent language if you know what to avoid
### So, you're writing an app ```javascript const express = require('express') const app = express() app.get('/answer/to/:anything',function(req,res){ res.status(200).send('42') }) app.listen(1337) ```
### Running in production * `node app.js` - forget it * `forever`, `cluster` - no, thanks * PM2! http://pm2.keymetrics.io/ * Containers / Docker / Now * Serverless - AWS Lambda etc. > PM2 is a production process manager for Node.js applications with a built-in load balancer. It allows you to keep applications alive forever, to reload them without downtime and to facilitate common system admin tasks.

Process Manager FTW

### Containers Back to `node app.js` but with all features of a process manager extracted outside and great infrastructure building/scaling tools.
### Serverless * You only write the logic, * Infrastructure, http layer and scaling is already provided * You pay for number of function runs, not servers waiting for traffic > Mindblowing, but not applicable for everyone
### Basic monitoring * server resources * is app running * can app be accessed >If your company (like mine) has centralized monitoring already, you're better off leveraging that. >The best monitoring is the one that has someone looking at it
But first ## Some good practices for writing the app
### Stateless * No client information exists in the app between requests * Multiple copies of the app can handle requests from the same user * Stateless = simple horizontal scaling * Redis for shared temporary state (sessions etc.)
![ASYNCHRONOUS](async.jpg) Promises! Did you know asynchronous JSON parsers exist?
### Enforce types sometimes >Dude, you're talking about JS, right? * Some important objects that carry data through your app need to have checks on them. * Tiny tools like [strongly-typed](https://github.com/naugtur/strongly-typed) can be enough. And are easy to add to an existing app * You can go all in and use Typescript or facebook's Flow.
### Feature toggles Good for keeping your master branch deployable. * Make them easy to find in code * Always remove them after no longer needed * Don't put tons of `if`s in code, duplicate a file and `require` depending on toggle value
## Manage dependencies * When in doubt, `npm shrinkwrap` * Don't install unmaintained code if it saves you 3 lines * Node Security Project and requireSafe ![nsp check](nsp.png)
## Getting dependencies to production * npm install with shrinkwrap file? - not bulletproof * `yarn` - a more precise npm client * `secure-dependencies` for bundling dependencies as build artifacts * bundle the whole app - use docker
## secure dependencies *never run npm install in production again!* [https://github.com/naugtur/secure-dependencies](https://github.com/naugtur/secure-dependencies) ``` npm install secure-dependencies --save-dev ``` ```js "scripts": { "bundle": "secure-dependencies" }, ``` `npm run bundle` --> myapp-1.0.0.tgz
# And now we're in production
## Logging * Use log levels * Enable changing log level without restarting the app. Most bugs stop reproducing after you restart. * IF you expect more than one user, generate a random ID for each HTTP request and add it to all logs it generates. ![info logs](logs.png)
## Sanitize * Logs should not contain user credentials etc. * Build a sanitizer that hashes sensitive data ``` [03-12_00:50:14.181] TRACE [75577] authorization: 'Bearer (sha256:bea5d8a8afabfb21b1b8234c23b12ea44f1180c6a96d53c5)' ```
## What to monitor I'm not going to go through features of tools like keymetrics or newRelic
## HTTP request time and status * Watch for 5XX and alert immediately. * Monitor other statuses for popularity. Too many 404s may be a problem too. * Keep statistics on response time separately for every endpoint * Time requests made by the app
## Loop blocks * Use `blocked` to detect ``` blocked(function(ms){ console.log('BLOCKED FOR %s ms', ms | 0); }); ``` * Finding them is harder. My little experiment: [promise-blocked](https://github.com/naugtur/promise-blocked) * Some monitoring tools integrate with node to do that
## Memory increase * Node.js will shutdown when 1.5GB gets allocated * Monitor `process.memoryUsage().rss` * Watch for steady increase in memory use
## Debugging memory leaks * `v8-profiler` in dev/staging * Simple [tutorial](https://github.com/felixge/node-memory-leak-tutorial), but very old * In production - take a heapdump and then another, compare It's an old topic, noone is getting into a conference lineup with it, so no new content. I have some fresh content about it, for training. (private use permitted)
## maintenance endpoint Create a separate http server listening on `localhost:1337` that will handle: * Switching log level without restart * Generating a heapdump * Healthcheck endpoint (can also be public) * Runing scripts for diagnostics or data migration * Returning basic stats for monitoring (unless you're using tools that integrate directly into node)
## Things I didn't squeeze into the presentation * Getting and using heapdumps * Error handler shared across the app * Much more security tips * Safe, non leaking, object caches * No-downtime redeploys
## Advanced debugging in production Recent [talk](http://techblog.netflix.com/2015/12/debugging-nodejs-in-production.html) from Netflix is a must. * Flame graphs [2014 at Netflix](http://techblog.netflix.com/2014/11/nodejs-in-flames.html) * Joyent had flame graphs [long ago](http://www.joyent.com/blog/walmart-node-js-memory-leak) * Postmortem debugging from a core dump with `mdb` on smartos * [Post Mortem Diagnostics Working Group](https://github.com/nodejs/post-mortem)

Follow me for workshops on this

@naugtur
http://naugtur.pl

Subscribe to my newsletter http://naugtur.pl/news and get:

  • notifications about events I organize before everyone else (think tickets)
  • access to learning resources I produce
  • no spam, less than 1 email a month on average