# 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
PORTenvironment variable to8080(or useprocess.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
pidusageis installed:npm install pidusage - On Windows, ensure WMI is enabled
- Check that
limit<maxin configuration
Memory Leaks in Long-Running Processes
Issue: Growing memory usage over time Solution:
- Enable audit logging to track request patterns
- Use
pm2with 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.