Getting your Node.js app production ready

Practical guide

@naugtur, meet.js summit 2016

### 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 on a server * `node app.js` - forget it * `forever`, `cluster` - meh * PM2! >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

### 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) Did you know asynchronous JSON parsers exist?
### Enforce types sometimes >Dude, you're on a JS conference * Some important objects that carry data through your app need to have checks on them. * Tiny tools like [strongly-typed]( can be enough. And are easy to add to an existing app * You can go all in and use Typescript.
## 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)
# And now we're in production
## Logging 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)
## Use log levels * Fatal, Error are pretty obvious * Warn can be an error you don't mind * Info is for tracking what app does regularly * Debug is for logs that help you understand what's up * Trace should contain enough data to reproduce Enable changing log level without restarting the app. Most bugs stop reproducing after you restart.
## 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. For promises, try [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]( from 5yr ago * In production - take a heapdump and then another, compare
## Heapdump Only require the heapdump module when something weird is happening and you want the snapshot. ``` javascript function dumpRequestHandler(req, res) { var heapdump = require("heapdump"); heapdump.writeSnapshot(function (err, filename) { res.end(err || ("see: " + process.cwd() + "/" + filename) ); }); } ``` Don't make it publicly available!
## maintenance endpoint Create a separate express app listening on `localhost:1337` that will handle: * Switching log level without restart * Generating a heapdump * Healthcheck endpoint * Runing scripts for diagnostics or data migration * Returning basic stats for monitoring (unless you're using tools that integrate directly into node)
## Debugging in production Recent [talk]( from Netflix is a must. * Flame graphs [2014 at Netflix]( * Joyent had flame graphs [long ago]( * Postmortem debugging from a core dump * `mdb` works on smartos, so you need a VM * [Post Mortem Diagnostics Working Group](
## Things I didn't squeeze into the presentation * Error handler shared across the app * Feature toggles * Much more security tips * Safe, non leaking, object caches * No-downtime redeploys

Follow me for workshops on this


Subscribe to my newsletter and get:

  • notifications about events I organize before everyone else (think tickets)
  • access to learning resources I produce
  • no spam, at most 2 mails a month