Error Handling
Handling Uncaught Exceptions
- Unless developers explicitly add
.catchstatements, errors thrown in these areas will not be handled by theuncaughtExceptionevent handler and will silently disappear. - While Node applications won’t crash, this can lead to memory leaks.
process.on('uncaughtException', (error) => {
// I just received an unhandled error
// Now handle it and decide whether to restart the application
errorManagement.handler.handleError(error);
if (!errorManagement.handler.isTrustedError(error)) {
process.exit(1);
}
});
process.on('unhandledRejection', (reason, p) => {
// I just caught an unhandled promise rejection
// Since we already have a fallback mechanism for unhandled errors (see below)
// Throw it to let the fallback handle it
throw reason;
});Managing Exceptions with Domain
- Create an instance using the
createmethod of thedomainmodule. - Any error, along with other errors, will be handled by the same error-handling method.
- Any code that causes errors within this callback will be covered by the domain.
- Allows code to run in a sandbox and provides feedback to users using the
resobject.
const domain = require('domain');
const audioDomain = domain.create();
audioDomain.on('error', function (err) {
console.log('audioDomain error:', err);
});
audioDomain.run(function () {
const musicPlayer = new MusicPlayer();
musicPlayer.play();
});Joi Parameter Validation
const memberSchema = Joi.object().keys({
password: Joi.string().regex(/^[a-zA-Z0-9]{3,30}$/),
birthyear: Joi.number().integer().min(1900).max(2013),
email: Joi.string().email(),
});
function addNewMember(newMember) {
// Assertions come first
Joi.assert(newMember, memberSchema); // Throws if validation fails
// Other logic here
}Kibana System Monitoring
See: Smart Logging Best Practices
Deployment Practices
Logging with Winston
const winston = require('winston');
const moment = require('moment');
const logger = new (winston.Logger)({
transports: [
new (winston.transports.Console)({
timestamp: function () {
return moment().format('YYYY-MM-DD HH:mm:ss');
},
formatter: function (params) {
let time = params.timestamp(); // Time
let message = params.message; // Manual message
let meta = params.meta && Object.keys(params.meta).length ? '\n\t' + JSON.stringify(params.meta) : '';
return `${time} ${message}`;
},
}),
new (winston.transports.File)({
filename: `${__dirname}/../winston/winston.log`,
json: false,
timestamp: function () {
return moment().format('YYYY-MM-DD HH:mm:ss');
},
formatter: function (params) {
let time = params.timestamp(); // Time
let message = params.message; // Manual message
let meta = params.meta && Object.keys(params.meta).length ? '\n\t' + JSON.stringify(params.meta) : '';
return `${time} ${message}`;
},
}),
],
});
module.exports = logger;
// logger.error('error')
// logger.warn('warn')
// logger.info('info')Delegating to a Reverse Proxy
Node performs poorly with CPU-intensive tasks like gzipping and SSL termination. Instead, use a dedicated middleware service like Nginx, which handles these tasks more efficiently. Otherwise, Node’s single-threaded nature will be bogged down by network tasks, reducing performance and impacting the application core.
While express.js can serve static files via Connect middleware, this is not recommended. Nginx handles static files more effectively and prevents requests for dynamic content from blocking the Node process.
# Configure gzip compression
gzip on;
gzip_comp_level 6;
gzip_vary on;
# Configure upstream
upstream myApplication {
server 127.0.0.1:3000;
server 127.0.0.1:3001;
keepalive 64;
}
# Define web server
server {
# Configure server with SSL and error pages
listen 80;
listen 443 ssl;
ssl_certificate /some/location/sillyfacesociety.com.bundle.crt;
error_page 502 /errors/502.html;
# Handling static content
location ~ ^/(images/|img/|javascript/|js/|css/|stylesheets/|flash/|media/|static/|robots.txt|humans.txt|favicon.ico) {
root /usr/local/silly_face_society/node/public;
access_log off;
expires max;
}
}Detecting Vulnerable Dependencies
PM2 HTTP Cluster Configuration
Worker Thread Configuration
pm2 start app.js -i 4: The-i 4flag runs the app in cluster mode with 4 worker threads. If set to0, PM2 will spawn threads based on the CPU core count.- PM2 automatically restarts worker threads if they crash.
pm2 scale <app name> <n>: Scales the cluster.
PM2 Auto-Start
pm2 save: Saves the current running applications.pm2 startup: Configures auto-start.



