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! http://pm2.keymetrics.io/
>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.
### 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](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.
## 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](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) 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](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
* `mdb` works on smartos, so you need a VM
* [Post Mortem Diagnostics Working Group](https://github.com/nodejs/post-mortem)
## 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
@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, at most 2 mails a month