← Back to restify/node-restify

How to Deploy & Use restify/node-restify

# Restify Deployment and Usage Guide

A comprehensive guide for deploying and using the restify Node.js REST framework.

## Prerequisites

- **Node.js**: Version 14.x or 16.x (restify currently supports only these versions)
- **npm**: Bundled with Node.js (v6+ recommended)
- **Git**: For cloning examples and repositories
- **Optional**: DTrace support (for performance monitoring on supported platforms)

## Installation

### Basic Setup

```bash
# Initialize your project
npm init -y

# Install restify core
npm install restify

# Install client libraries (optional, for service-to-service communication)
npm install restify-clients

# Install error handling utilities
npm install restify-errors

Development Dependencies

# Recommended for production logging
npm install pino

# For CPU throttling capabilities
npm install pidusage ewma

Configuration

Server Configuration

Create a server with core options:

const restify = require('restify');

const server = restify.createServer({
  name: 'myapp',
  version: '1.0.0',
  // Optional: SSL configuration
  // certificate: fs.readFileSync('cert.pem'),
  // key: fs.readFileSync('key.pem'),
  // formatters: customFormatters
});

Essential Middleware Setup

// Content negotiation and parsing
server.use(restify.plugins.acceptParser(server.acceptable));
server.use(restify.plugins.queryParser());
server.use(restify.plugins.bodyParser());

// Security and CORS
server.use(restify.plugins.authorizationParser());

// Request logging (using pino)
server.use(restify.plugins.requestLogger());

Environment Variables

# Server configuration
PORT=8080
NODE_ENV=production

# CPU Throttling (optional)
CPU_LIMIT=0.5          # Target CPU utilization (0-1)
CPU_MAX=1.0            # Maximum CPU before 100% rejection
CPU_INTERVAL=250       # Measurement interval in ms
CPU_HALFLIFE=250       # EWMA half-life in ms

# Audit logging
AUDIT_LOG=true
AUDIT_PRINT_LOG=true

Advanced: CPU Usage Throttling

Protect against cascading failures under load:

server.use(restify.plugins.cpuUsageThrottle({
  limit: 0.5,        // Target 50% CPU utilization
  max: 1.0,          // Reject 100% at 100% CPU
  interval: 250,     // Check every 250ms
  halfLife: 250      // EWMA decay rate
}));

Audit Logging Configuration

server.on('after', restify.plugins.auditLogger({
  event: 'after',
  log: pino({ level: 'info' }),
  server: server,
  printLog: true,
  context: function (req, res, route, err) {
    return {
      route: route && route.name,
      user: req.username
    };
  }
}));

Build & Run

Development Mode

// server.js
const restify = require('restify');

const server = restify.createServer({
  name: 'myapp',
  version: '1.0.0'
});

server.use(restify.plugins.acceptParser(server.acceptable));
server.use(restify.plugins.queryParser());
server.use(restify.plugins.bodyParser());

server.get('/echo/:name', function (req, res, next) {
  res.send(req.params);
  return next();
});

server.listen(8080, function () {
  console.log('%s listening at %s', server.name, server.url);
});

Run:

node server.js

Production Mode

Use a process manager for clustering (restify is single-threaded):

# Using PM2
npm install -g pm2
pm2 start server.js -i max --name restify-api

# Or with environment variables
PORT=8080 NODE_ENV=production pm2 start server.js -i max

Client Usage Example

const clients = require('restify-clients');

const client = clients.createJsonClient({
  url: 'http://localhost:8080',
  version: '~1.0'
});

client.get('/echo/mark', function (err, req, res, obj) {
  if (err) {
    console.error(err);
    return;
  }
  console.log('Server returned: %j', obj);
});

Deployment

Docker Deployment

FROM node:16-alpine
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
COPY . .
EXPOSE 8080
CMD ["node", "server.js"]

Build and run:

docker build -t restify-app .
docker run -p 8080:8080 -e NODE_ENV=production restify-app

Platform-Specific Deployment

Heroku:

# Procfile
web: node server.js

AWS Elastic Beanstalk:

  • Use Node.js 16 platform
  • Set PORT environment variable to 8080 (or use process.env.PORT)

DigitalOcean App Platform:

  • Set build command: npm install
  • Set run command: node server.js

Load Balancer Configuration

When deploying behind a load balancer (Nginx/HAProxy):

// Trust proxy headers
server.pre(restify.plugins.pre.userAgentConnection());

// Handle X-Forwarded-For
server.use(function(req, res, next) {
  if (req.headers['x-forwarded-for']) {
    req.connection.remoteAddress = req.headers['x-forwarded-for'].split(',')[0];
  }
  return next();
});

Troubleshooting

Node Version Compatibility

Issue: Error: Cannot find module or unexpected crashes Solution: Verify Node version matches supported versions (14.x or 16.x):

node --version
# If not 14.x or 16.x, use nvm to switch
nvm install 16
nvm use 16

Middleware Order Issues

Issue: Request body undefined or parsing errors Solution: Ensure bodyParser is registered before route handlers:

// Correct order
server.use(restify.plugins.bodyParser());
server.post('/api/data', handler);

// Incorrect: bodyParser after route definition will fail

CPU Throttling Not Working

Issue: pidusage errors or no throttling occurring Solution:

  • Ensure pidusage is installed: npm install pidusage
  • On Windows, ensure WMI is enabled
  • Check that limit < max in configuration

Memory Leaks in Long-Running Processes

Issue: Growing memory usage over time Solution:

  • Enable audit logging to track request patterns
  • Use pm2 with memory limits: pm2 start server.js --max-memory-restart 500M
  • Check for closure leaks in middleware

DTrace Errors on macOS/Linux

Issue: DTraceProviderBindings errors on startup Solution:

# macOS
npm install -g dtrace-provider

# Linux (if DTrace not available)
npm install restify --no-optional

Content Negotiation Failures

Issue: 406 Not Acceptable errors Solution: Ensure acceptParser middleware is registered with server.acceptable array:

server.use(restify.plugins.acceptParser(server.acceptable));

Custom Error Handling

For application-specific errors (based on todoapp example):

const errors = require('restify-errors');

const TodoNotFoundError = errors.makeConstructor('TodoNotFoundError', {
    statusCode: 404,
    restCode: 'TodoNotFound',
    message: 'Todo was not found'
});

server.get('/todos/:id', function(req, res, next) {
  if (!todoExists(req.params.id)) {
    return next(new TodoNotFoundError());
  }
  res.send(todo);
  return next();
});

For additional support, see the restify documentation or GitHub Issues.