On this page
Deployment
Moving from local development to production requires process management, environment configuration, and monitoring.
Production Checklist
- Set
NODE_ENV=production - Use environment variables for all secrets
- Enable HTTPS
- Set up logging and monitoring
- Configure health check endpoints
- Use a process manager
Health Check Endpoint
app.get('/health', (req, res) => {
res.json({ status: 'ok', uptime: process.uptime() });
});
PM2 Process Manager
npm install -g pm2
pm2 start src/index.js --name my-api
pm2 logs my-api
pm2 restart my-api
pm2 stop my-api
# Auto-restart on server reboot
pm2 startup
pm2 save
ecosystem.config.js:
module.exports = {
apps: [{
name: 'my-api',
script: 'src/index.js',
instances: 'max',
exec_mode: 'cluster',
env: {
NODE_ENV: 'production',
PORT: 3000
}
}]
};
pm2 start ecosystem.config.js
Docker
Dockerfile:
FROM node:20-alpine
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
COPY . .
EXPOSE 3000
CMD ["node", "src/index.js"]
docker build -t my-api .
docker run -p 3000:3000 --env-file .env my-api
Cloud Platforms
| Platform | Best for |
|---|---|
| Railway | Quick deploys, hobby projects |
| Render | Free tier, auto-deploy from Git |
| Fly.io | Global edge deployment |
| AWS ECS/Lambda | Enterprise scale |
| Vercel | Serverless functions |
Environment on Cloud
Set variables in the platform dashboard — never commit .env to git.
Graceful Shutdown
const server = app.listen(PORT);
process.on('SIGTERM', () => {
console.log('SIGTERM received, shutting down gracefully');
server.close(() => {
mongoose.connection.close(false, () => process.exit(0));
});
});
Logging
Use structured logging in production:
npm install winston
import winston from 'winston';
const logger = winston.createLogger({
level: 'info',
format: winston.format.json(),
transports: [
new winston.transports.File({ filename: 'error.log', level: 'error' }),
new winston.transports.File({ filename: 'combined.log' })
]
});
if (process.env.NODE_ENV !== 'production') {
logger.add(new winston.transports.Console({ format: winston.format.simple() }));
}
Deploy early and often — start with a simple platform like Render or Railway, then scale as needed.