Node.
js Complete Guide
Part 10: Deployment and DevOps
Taking Your Application to Production
Part 10 of 10-Part Series
Deploying [Link] applications to production requires careful planning and
implementation of robust DevOps practices. In this final part of our
comprehensive guide, we'll explore production deployment strategies,
containerization with Docker, orchestration with Kubernetes, cloud platform
integration, environment management, monitoring and logging solutions, and
performance optimization techniques to ensure your applications run reliably at
scale.
1. Production Deployment Strategies
1.1 Process Managers
PM2 - Production Process Manager
npm install -g pm2
# Start application
pm2 start [Link] --name my-app
# Start with cluster mode (uses all CPU cores)
pm2 start [Link] -i max
# Common PM2 commands
pm2 list # List all processes
pm2 logs my-app # View logs
pm2 restart my-app # Restart application
pm2 stop my-app # Stop application
pm2 delete my-app # Remove from PM2
pm2 monit # Monitor resources
# Zero-downtime reload
pm2 reload my-app
1.2 PM2 Ecosystem File
// [Link]
[Link] = {
apps: [{
name: 'my-app',
script: './[Link]',
instances: 'max',
exec_mode: 'cluster',
env: {
NODE_ENV: 'production',
PORT: 3000
},
error_file: './logs/[Link]',
out_file: './logs/[Link]',
log_date_format: 'YYYY-MM-DD HH:mm:ss',
max_memory_restart: '1G',
watch: false,
ignore_watch: ['node_modules', 'logs']
}]
};
# Start with ecosystem file
pm2 start [Link]
1.3 Systemd Service (Linux)
# /etc/systemd/system/[Link]
[Unit]
Description=My [Link] App
After=[Link]
[Service]
Type=simple
User=nodeuser
WorkingDirectory=/opt/myapp
Environment=NODE_ENV=production
ExecStart=/usr/bin/node /opt/myapp/[Link]
Restart=always
RestartSec=10
[Install]
WantedBy=[Link]
# Enable and start service
sudo systemctl enable myapp
sudo systemctl start myapp
sudo systemctl status myapp
2. Docker Containerization
2.1 Creating a Dockerfile
# Dockerfile
# Use official [Link] LTS image
FROM node:20-alpine
# Set working directory
WORKDIR /app
# Copy package files
COPY package*.json ./
# Install dependencies
RUN npm ci --only=production
# Copy application code
COPY . .
# Create non-root user
RUN addgroup -g 1001 -S nodejs && adduser -S nodejs -u 1001
USER nodejs
# Expose port
EXPOSE 3000
# Start application
CMD ["node", "[Link]"]
2.2 Multi-stage Dockerfile
# Build stage
FROM node:20-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build
# Production stage
FROM node:20-alpine
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
COPY --from=builder /app/dist ./dist
RUN addgroup -g 1001 -S nodejs && adduser -S nodejs -u 1001
USER nodejs
EXPOSE 3000
CMD ["node", "dist/[Link]"]
2.3 .dockerignore
# .dockerignore
node_modules
[Link]
.env
.git
.gitignore
[Link]
coverage
dist
2.4 Docker Compose
# [Link]
version: '3.8'
services:
app:
build: .
ports:
- "3000:3000"
environment:
- NODE_ENV=production
- DATABASE_URL=postgresql://user:pass@db:5432/mydb
- REDIS_URL=redis://redis:6379
depends_on:
- db
- redis
restart: unless-stopped
db:
image: postgres:16-alpine
environment:
- POSTGRES_USER=user
- POSTGRES_PASSWORD=pass
- POSTGRES_DB=mydb
volumes:
- postgres_data:/var/lib/postgresql/data
redis:
image: redis:7-alpine
volumes:
- redis_data:/data
volumes:
postgres_data:
redis_data:
# Start all services
docker-compose up -d
3. Kubernetes Orchestration
3.1 Deployment Configuration
# [Link]
apiVersion: apps/v1
kind: Deployment
metadata:
name: myapp
spec:
replicas: 3
selector:
matchLabels:
app: myapp
template:
metadata:
labels:
app: myapp
spec:
containers:
- name: myapp
image: myapp:latest
ports:
- containerPort: 3000
env:
- name: NODE_ENV
value: production
resources:
requests:
memory: "256Mi"
cpu: "250m"
limits:
memory: "512Mi"
cpu: "500m"
livenessProbe:
httpGet:
path: /health
port: 3000
initialDelaySeconds: 30
periodSeconds: 10
readinessProbe:
httpGet:
path: /ready
port: 3000
initialDelaySeconds: 10
periodSeconds: 5
3.2 Service Configuration
# [Link]
apiVersion: v1
kind: Service
metadata:
name: myapp-service
spec:
selector:
app: myapp
ports:
- protocol: TCP
port: 80
targetPort: 3000
type: LoadBalancer
3.3 ConfigMap and Secrets
# [Link]
apiVersion: v1
kind: ConfigMap
metadata:
name: myapp-config
data:
APP_NAME: MyApplication
LOG_LEVEL: info
# [Link]
apiVersion: v1
kind: Secret
metadata:
name: myapp-secrets
type: Opaque
data:
DATABASE_URL: cG9zdGdyZXNxbDovL3VzZXI6cGFzc0BkYjo1NDMyL215ZGI=
JWT_SECRET: c2VjcmV0a2V5MTIzNDU2
4. Cloud Platform Deployment
4.1 AWS Deployment
Elastic Beanstalk
# Install EB CLI
pip install awsebcli
# Initialize EB application
eb init
# Create environment
eb create production-env
# Deploy application
eb deploy
ECS (Elastic Container Service)
# Build and push Docker image to ECR
aws ecr get-login-password --region us-east-1 | docker login --username AWS --password-
stdin [Link]
docker build -t myapp .
docker tag myapp:latest [Link]/myapp:latest
docker push [Link]/myapp:latest
4.2 Azure Deployment
# Install Azure CLI
curl -sL [Link] | sudo bash
# Login to Azure
az login
# Create resource group
az group create --name myapp-rg --location eastus
# Create App Service plan
az appservice plan create --name myapp-plan --resource-group myapp-rg --is-linux --sku B1
# Create web app
az webapp create --resource-group myapp-rg --plan myapp-plan --name myapp --runtime
"NODE:20-lts"
# Deploy from GitHub
az webapp deployment source config --name myapp --resource-group myapp-rg --repo-url
[Link] --branch main
4.3 Google Cloud Platform
# Install gcloud CLI
curl [Link] | bash
# Initialize and authenticate
gcloud init
# Deploy to App Engine
gcloud app deploy
# [Link] for App Engine
runtime: nodejs20
env: standard
instance_class: F2
automatic_scaling:
target_cpu_utilization: 0.65
min_instances: 1
max_instances: 10
5. Environment Management
5.1 Environment Variables
// [Link]
[Link] = {
port: [Link] || 3000,
nodeEnv: [Link].NODE_ENV || 'development',
database: {
url: [Link].DATABASE_URL,
pool: {
min: parseInt([Link].DB_POOL_MIN) || 2,
max: parseInt([Link].DB_POOL_MAX) || 10
}
},
redis: {
url: [Link].REDIS_URL
},
jwt: {
secret: [Link].JWT_SECRET,
expiresIn: [Link].JWT_EXPIRES_IN || '24h'
},
logging: {
level: [Link].LOG_LEVEL || 'info'
}
};
5.2 Configuration Validation
npm install joi
// [Link]
const Joi = require('joi');
const envSchema = [Link]({
NODE_ENV: [Link]().valid('development', 'production', 'test').required(),
PORT: [Link]().default(3000),
DATABASE_URL: [Link]().uri().required(),
REDIS_URL: [Link]().uri().required(),
JWT_SECRET: [Link]().min(32).required(),
LOG_LEVEL: [Link]().valid('error', 'warn', 'info', 'debug').default('info')
}).unknown();
const { error } = [Link]([Link]);
if (error) {
throw new Error(`Config validation error: ${[Link]}`);
}
6. Monitoring and Logging
6.1 Structured Logging with Winston
npm install winston
// [Link]
const winston = require('winston');
const logger = [Link]({
level: [Link].LOG_LEVEL || 'info',
format: [Link](
[Link](),
[Link]({ stack: true }),
[Link]()
),
defaultMeta: { service: 'myapp' },
transports: [
new [Link]({
format: [Link](
[Link](),
[Link]()
)
}),
new [Link]({ filename: '[Link]', level: 'error' }),
new [Link]({ filename: '[Link]' })
]
});
[Link] = logger;
6.2 Application Performance Monitoring
New Relic Integration
npm install newrelic
// [Link]
[Link] = {
app_name: ['My Application'],
license_key: [Link].NEW_RELIC_LICENSE_KEY,
logging: {
level: 'info'
}
};
// [Link] - require at the very top
require('newrelic');
6.3 Health Check Endpoints
// [Link]
const express = require('express');
const router = [Link]();
// Liveness probe - is the app running?
[Link]('/health', (req, res) => {
[Link](200).json({ status: 'ok' });
});
// Readiness probe - can it serve traffic?
[Link]('/ready', async (req, res) => {
try {
// Check database connection
await [Link]('SELECT 1');
// Check Redis connection
await [Link]();
[Link](200).json({ status: 'ready' });
} catch (error) {
[Link](503).json({ status: 'not ready', error: [Link] });
}
});
[Link] = router;
7. Performance Optimization
7.1 Compression
npm install compression
const compression = require('compression');
const express = require('express');
const app = express();
// Enable gzip compression
[Link](compression({
level: 6, // Compression level 0-9
threshold: 1024 // Only compress responses > 1KB
}));
7.2 Caching Strategies
npm install redis
const redis = require('redis');
const client = [Link]({ url: [Link].REDIS_URL });
// Cache middleware
async function cacheMiddleware(req, res, next) {
const key = `cache:${[Link]}`;
try {
const cached = await [Link](key);
if (cached) {
return [Link]([Link](cached));
}
// Store original send function
const originalSend = [Link];
// Override send to cache the response
[Link] = function(data) {
[Link](key, 3600, [Link](data)); // 1 hour TTL
[Link](this, data);
};
next();
} catch (error) {
next();
}
}
7.3 Database Connection Pooling
// PostgreSQL with pg pool
const { Pool } = require('pg');
const pool = new Pool({
connectionString: [Link].DATABASE_URL,
max: 20, // Maximum pool size
min: 5, // Minimum pool size
idleTimeoutMillis: 30000, // Close idle connections
connectionTimeoutMillis: 2000
});
7.4 Clustering for Multi-core Systems
// [Link]
const cluster = require('cluster');
const os = require('os');
if ([Link]) {
const numCPUs = [Link]().length;
[Link](`Master process ${[Link]} starting ${numCPUs} workers`);
// Fork workers
for (let i = 0; i < numCPUs; i++) {
[Link]();
}
// Restart worker on exit
[Link]('exit', (worker, code, signal) => {
[Link](`Worker ${[Link]} died, starting new worker`);
[Link]();
});
} else {
// Worker process - run the application
require('./[Link]');
[Link](`Worker ${[Link]} started`);
}
8. Security Best Practices
8.1 Security Middleware
npm install helmet express-rate-limit
const helmet = require('helmet');
const rateLimit = require('express-rate-limit');
// Apply security headers
[Link](helmet());
// Rate limiting
const limiter = rateLimit({
windowMs: 15 * 60 * 1000, // 15 minutes
max: 100, // Limit each IP to 100 requests per window
standardHeaders: true,
legacyHeaders: false
});
[Link]('/api/', limiter);
8.2 Secrets Management
Using AWS Secrets Manager
npm install @aws-sdk/client-secrets-manager
const { SecretsManagerClient, GetSecretValueCommand } = require('@aws-sdk/client-
secrets-manager');
async function getSecret(secretName) {
const client = new SecretsManagerClient({ region: 'us-east-1' });
try {
const response = await [Link](
new GetSecretValueCommand({ SecretId: secretName })
);
return [Link]([Link]);
} catch (error) {
throw error;
}
}
8.3 SSL/TLS Configuration
const https = require('https');
const fs = require('fs');
const options = {
key: [Link]('[Link]'),
cert: [Link]('[Link]')
};
[Link](options, app).listen(443);
9. Continuous Deployment
9.1 GitHub Actions CD Pipeline
# .github/workflows/[Link]
name: Deploy to Production
on:
push:
branches:
- main
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
with:
node-version: 20
- run: npm ci
- run: npm test
build:
needs: test
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: docker/login-action@v2
with:
registry: [Link]
username: ${{ [Link] }}
password: ${{ secrets.GITHUB_TOKEN }}
- uses: docker/build-push-action@v4
with:
context: .
push: true
tags: [Link]/${{ [Link] }}:latest
deploy:
needs: build
runs-on: ubuntu-latest
steps:
- name: Deploy to Kubernetes
uses: azure/k8s-deploy@v4
with:
manifests: |
k8s/[Link]
k8s/[Link]
images: [Link]/${{ [Link] }}:latest
9.2 Blue-Green Deployment
Blue-green deployment strategy minimizes downtime by running two identical
production environments:
Blue environment runs the current production version
Green environment receives the new version
After testing, traffic is switched to green
Blue becomes the standby for quick rollback
# [Link]
apiVersion: apps/v1
kind: Deployment
metadata:
name: myapp-blue
spec:
replicas: 3
selector:
matchLabels:
app: myapp
version: blue
# Switch traffic to green by updating service selector
kubectl patch service myapp -p '{"spec":{"selector":{"version":"green"}}}'
10. Summary
In this final part of the [Link] Complete Guide, we explored comprehensive
deployment and DevOps practices:
Production deployment strategies with PM2 and systemd
Docker containerization with multi-stage builds
Kubernetes orchestration for scalable deployments
Cloud platform integration (AWS, Azure, GCP)
Environment configuration and secrets management
Monitoring, logging, and health checks
Performance optimization techniques
Security best practices and middleware
Continuous deployment pipelines
Advanced deployment strategies
Successful deployment requires more than just pushing code to a server. It
demands careful attention to infrastructure, monitoring, security, and operational
excellence. By implementing these practices, you ensure your [Link]
applications are reliable, scalable, and maintainable in production.
Conclusion
Congratulations on completing the [Link] Complete Guide! Throughout this 10-
part series, you've learned:
[Link] fundamentals and the event loop
Asynchronous programming patterns
[Link] and RESTful API development
Database integration (SQL and NoSQL)
Authentication and security
Real-time applications with WebSockets
Microservices architecture
GraphQL APIs
Testing and quality assurance
Deployment and DevOps practices
You now have the knowledge and skills to build production-ready [Link]
applications. Continue practicing, exploring new technologies, and staying
current with the [Link] ecosystem. The journey of learning never ends, and the
[Link] community is vibrant and welcoming.
Thank you for following this guide. Build amazing things!