Introduction
PM2 is an open-source process manager for Node.js, the go-to standard in 2026 for production deployments. Unlike a basic node app.js, PM2 provides automatic restarts on crashes, cluster mode for horizontal scaling, real-time monitoring via web dashboard, and zero-downtime deploys.
Why use it? Picture your API crashing at 3 AM: PM2 restarts it in milliseconds without human intervention. For beginner devs, it's like upgrading from a bicycle to an automatic car—everything's handled. This tutorial takes you from installation to production, packed with 1500+ words of pure value: full code snippets, copy-paste configs, and pitfalls avoided. By the end, your app will be robust, monitored, and scalable. Ideal for freelancers or startups wanting reliability without complex DevOps.
Prerequisites
- Node.js 20+ installed (check with
node -v) - npm or yarn
- A basic Node.js app (we'll create one)
- Unix-like terminal (WSL on Windows is fine)
- Minimal JavaScript knowledge
Install PM2 Globally
npm install pm2@latest -g
npm audit fix --forceThis command installs PM2 globally so you can use it anywhere. The @latest flag ensures the stable 2026 version (5.x+). npm audit fix patches potential vulnerabilities right away, dodging common production security pitfalls.
Create a Test Node.js App
Before diving into PM2, let's build a simple Express app for testing. It's our playground: an HTTP server responding on / and /health. Copy this code into a project folder (mkdir my-app && cd my-app). Think of it as scaffolding to validate PM2 without added complexity.
Create the Express Server
const express = require('express');
const app = express();
const PORT = process.env.PORT || 3000;
app.get('/', (req, res) => {
res.json({ message: 'Hello PM2!', timestamp: new Date().toISOString() });
});
app.get('/health', (req, res) => {
res.status(200).json({ status: 'OK', uptime: process.uptime() });
});
app.listen(PORT, () => {
console.log(`Server running on port ${PORT}`);
});This complete Express server handles two routes and reads PORT from env vars for production. It's basic crash-proof. Pitfall: without PM2, Ctrl+C kills everything; here, we're prepping for daemon mode.
Install Dependencies
npm init -y
npm install express
npm install --save-dev nodemonInitializes package.json, adds Express for the server, and nodemon for local dev (optional). In production, PM2 replaces nodemon. Avoids polluting global node_modules.
Launch the App with Basic PM2
Let's test PM2 without any config. This is the 'wow' moment: your app runs in the background and survives machine restarts. Use pm2 list to check status—like a mini dashboard.
Start the App Simply
pm2 start server.js --name mon-api
pm2 save
pm2 startupLaunches server.js as 'mon-api', saves the process list (save), and sets up boot startup (startup—follow the instructions). Pitfall: without save, a reboot loses everything.
Configure with Ecosystem File
Pro level: Switch to ecosystem.config.js for scaling. It's a declarative JS file handling clusters, instances, and env vars. Like a recipe book for PM2—reproducible on any server.
Ecosystem Config File
module.exports = {
apps: [{
name: 'mon-api-cluster',
script: './server.js',
instances: 'max', // Utilise tous les CPU cores
exec_mode: 'cluster',
env: {
NODE_ENV: 'development',
PORT: 3000
},
env_production: {
NODE_ENV: 'production',
PORT: 3001
},
log_date_format: 'YYYY-MM-DD HH:mm Z',
error_file: './logs/err.log',
out_file: './logs/out.log',
time: true
}]
};Defines a clustered app (max = auto-scale to all CPU cores), with dev/prod envs. Separate logs with timestamps. Restart with pm2 start ecosystem.config.js --env production. Pitfall: instances: 1 without cluster = no scaling.
Restart in Production Mode
pm2 delete all
pm2 start ecosystem.config.js --env production
pm2 save
pm2 list
pm2 monitDeletes everything, relaunches in production (PORT=3001), saves, lists, and opens monitoring. monit is a real-time TUI dashboard (CPU, RAM, restarts). Zero downtime via clustering.
Monitoring and Logs
pm2 monit shows live metrics; pm2 logs for traces. In 2026, upgrade to PM2 Plus (paid) for a web dashboard. Test it: curl localhost:3001/health.
Useful Monitoring Commands
pm2 logs mon-api-cluster
pm2 show mon-api-cluster
pm2 restart mon-api-cluster
pm2 stop mon-api-cluster
pm2 delete mon-api-clusterFiltered logs, app details, soft restarts (zero-downtime), stop/delete. Ideal for production debugging without interruptions. Always name apps for precise targeting.
Best Practices
- Always use ecosystem.config.js: Git-friendly and reproducible vs. bash commands.
- Enable cluster mode (
instances: 'max') to scale across CPUs without code changes. - Separate logs (
error_file,out_file) and rotate withpm2 install pm2-logrotate. - Strict env vars:
NODE_ENV=production+ secrets via .env (dotenv). - Proactive monitoring: Run
pm2 monitin screen/tmux, alert on restarts >0.
Common Errors to Avoid
- Forgetting
pm2 saveandpm2 startup: Server reboot = dead apps. - No names (--name):
pm2 listbecomes chaotic with anonymous IDs. - Cluster without unique PORTs: Collisions; force per-instance PORTs if needed.
- Unconfigured logs: Fills /var/log, silences app in production.
Next Steps
- Official docs: PM2.io
- PM2 Plus for web dashboards and Slack alerts.
- Integrate with Docker: Use
pm2-runtimein your Dockerfile. - Check our Learni trainings on Node.js Production and DevOps to master PM2 in a team.