How to Use Pm2 for Nodejs
How to Use PM2 for Node.js Node.js has become the backbone of modern web applications, powering everything from REST APIs to real-time services and microservices architectures. However, running Node.js applications in production presents unique challenges: crashes, memory leaks, restart failures, and lack of process monitoring can bring down your entire system. This is where PM2 —Process Manager 2
How to Use PM2 for Node.js
Node.js has become the backbone of modern web applications, powering everything from REST APIs to real-time services and microservices architectures. However, running Node.js applications in production presents unique challenges: crashes, memory leaks, restart failures, and lack of process monitoring can bring down your entire system. This is where PM2Process Manager 2steps in as an essential tool for developers and DevOps engineers alike.
PM2 is a production-grade process manager for Node.js applications that ensures your apps stay online, automatically restart on failure, scale across CPU cores, and provide detailed logging and monitoring. Unlike running a Node.js app with node app.js, which terminates when the terminal closes or the process crashes, PM2 keeps your application alive and offers enterprise-grade features without requiring complex configuration.
In this comprehensive guide, youll learn how to install, configure, monitor, and optimize PM2 for production Node.js applications. Whether youre managing a single API server or a fleet of microservices, mastering PM2 will significantly improve your applications reliability, performance, and maintainability.
Step-by-Step Guide
Installing PM2
Before you can use PM2, you must install it globally on your system. PM2 is distributed via npm (Node Package Manager), so ensure Node.js and npm are installed on your machine. To verify, run:
node -v
npm -v
If these commands return version numbers, youre ready to proceed. Install PM2 globally using the following command:
npm install -g pm2
Once installed, confirm the installation by checking the PM2 version:
pm2 -v
You should see a version number (e.g., 5.3.1 or higher), confirming that PM2 is successfully installed and accessible from your terminal.
Starting a Node.js Application with PM2
Assume you have a basic Node.js application named app.js. To start it with PM2, navigate to your project directory and run:
pm2 start app.js
PM2 will output a summary of the process, including:
- App name
- Instance ID
- Mode (fork or cluster)
- PID
- Uptime
- Memory usage
- Current status
For example:
[PM2] Starting /path/to/app.js in fork_mode (1 instance)
[PM2] Done.
???????????????????????????????????????????????????????????????????????????????
? id ? name ? mode ? ? ? status ? cpu ? memory ?
???????????????????????????????????????????????????????????????????????????????
? 0 ? app ? fork ? 0 ? online ? 0% ? 25.6mb ?
???????????????????????????????????????????????????????????????????????????????
Your application is now running in the background, even if you close your SSH session or terminal.
Starting with a Custom Name
By default, PM2 uses the filename as the application name. To assign a custom name (useful when managing multiple apps), use the --name flag:
pm2 start app.js --name "my-api-server"
This makes it easier to identify and manage applications later, especially in environments with multiple services.
Starting in Cluster Mode for Better Performance
Node.js is single-threaded by default, meaning it only uses one CPU core. To fully utilize multi-core servers, PM2 offers cluster mode, which spawns multiple instances of your application, each running on a separate CPU core.
To start your app in cluster mode, use the -i flag followed by the number of instances:
pm2 start app.js -i max
The max keyword automatically detects the number of CPU cores and launches one process per core. Alternatively, specify a fixed number:
pm2 start app.js -i 4
Cluster mode not only improves performance under load but also enables zero-downtime reloads, which well cover shortly.
Using a Process File (ecosystem.config.js)
For production environments, manually typing commands is not scalable. PM2 supports configuration files to define application settings, environment variables, logging paths, and restart policies.
Generate a default ecosystem file with:
pm2 init
This creates an ecosystem.config.js file in your project root. Edit it to suit your needs:
module.exports = {
apps: [{
name: 'my-api-server',
script: './app.js',
instances: 'max',
exec_mode: 'cluster',
autorestart: true,
watch: false,
max_restarts: 10,
max_memory_restart: '1G',
env: {
NODE_ENV: 'development'
},
env_production: {
NODE_ENV: 'production',
PORT: 3000
}
}]
};
Key configuration options:
- name: A human-readable identifier for the app.
- script: Path to your main Node.js file.
- instances: Number of processes to spawn. Use
maxfor full CPU utilization. - exec_mode: Set to
clusterfor multi-core scaling. - autorestart: Automatically restart if the process crashes.
- watch: Enable file watching to auto-restart on code changes (useful in development).
- max_restarts: Maximum number of restarts within a time window to prevent loops.
- max_memory_restart: Restart if memory usage exceeds this limit (e.g., 1G).
- env and env_production: Environment-specific variables.
Start your app using the configuration file:
pm2 start ecosystem.config.js
To start in production mode, use:
pm2 start ecosystem.config.js --env production
PM2 will now use the env_production block from your config file.
Managing Running Applications
Once your app is running, PM2 provides several commands to manage it:
- List all apps:
pm2 list - View detailed info:
pm2 show <app-name>(e.g.,pm2 show my-api-server) - Stop an app:
pm2 stop <app-name> - Restart an app:
pm2 restart <app-name> - Reload an app (zero-downtime):
pm2 reload <app-name>(only works in cluster mode) - Delete an app:
pm2 delete <app-name> - Stop all apps:
pm2 stop all - Restart all apps:
pm2 restart all - Delete all apps:
pm2 delete all
Use pm2 monit to open a real-time monitoring dashboard showing CPU, memory, and network usage per process.
Enabling Auto-Start on System Boot
One of PM2s most powerful features is its ability to start your applications automatically when the server reboots. This is critical for production servers.
Run the following command to generate a startup script:
pm2 startup
PM2 will detect your system (Ubuntu, CentOS, macOS, etc.) and output a command to run with sudo privileges. For example:
[PM2] You have to run this command as root. Execute the following command:
sudo env PATH=$PATH:/usr/bin /usr/lib/node_modules/pm2/bin/pm2 startup systemd -u ubuntu --hp /home/ubuntu
Copy and paste the suggested command. This configures systemd (or init.d) to launch PM2 and all managed apps on boot.
Finally, save your current process list so its restored on reboot:
pm2 save
Now, even after a server restart, all your apps will automatically start with their previous configurations.
Viewing Logs in Real-Time
PM2 captures and stores logs for every application. To view logs for a specific app:
pm2 logs my-api-server
To view logs for all apps:
pm2 logs
Use the --raw flag to disable formatting:
pm2 logs --raw
To follow logs in real-time (like tail -f):
pm2 logs --tail 100
Logs are stored by default in ~/.pm2/logs/. You can customize the log path in your ecosystem.config.js:
log: '/var/log/myapp/output.log',
error: '/var/log/myapp/error.log',
Zero-Downtime Reloads
When deploying new code, you dont want to take your application offline. PM2 enables zero-downtime reloads using the reload command:
pm2 reload my-api-server
This command:
- Starts new worker processes with the updated code
- Gradually shuts down old workers after new ones are ready
- Ensures no requests are dropped
This is only possible in cluster mode. Always use reload instead of restart in production to avoid service interruptions.
Deploying with PM2
PM2 includes a built-in deployment tool that works with Git. First, create a deployment configuration in your ecosystem.config.js:
module.exports = {
apps: [{ ... }],
deploy: {
production: {
user: 'ubuntu',
host: 'your-server-ip',
ref: 'origin/main',
repo: 'git@github.com:yourusername/your-repo.git',
path: '/var/www/your-app',
'post-deploy': 'npm install && pm2 reload ecosystem.config.js --env production'
}
}
};
Then, deploy using:
pm2 deploy production setup
This creates the remote directory and clones your repo. Afterward, deploy code changes with:
pm2 deploy production update
PM2 will pull the latest code, install dependencies, and reload your appall automatically.
Best Practices
Always Use Cluster Mode in Production
Running Node.js in fork mode on a multi-core server is a waste of resources. Cluster mode leverages all available CPU cores, improves throughput, and enables zero-downtime reloads. Always use -i max or a number matching your core count.
Set Memory Limits to Prevent Crashes
Memory leaks are common in Node.js applications. Use max_memory_restart to automatically restart processes that exceed memory thresholds (e.g., 1G). This prevents gradual degradation and keeps your app responsive.
Use Environment-Specific Configurations
Never hardcode database URLs, API keys, or ports. Use env and env_production blocks in your ecosystem.config.js to manage different environments cleanly.
Log Rotation and Cleanup
Logs can grow rapidly and consume disk space. Configure log rotation by installing pm2-logrotate:
pm2 install pm2-logrotate
By default, it rotates logs daily, keeps 30 days of logs, and compresses old files. Customize it with:
pm2 set pm2-logrotate:max_size 10M
pm2 set pm2-logrotate:retain 14
pm2 set pm2-logrotate:compress true
pm2 set pm2-logrotate:dateFormat YYYY-MM-DD_HH-mm-ss
Monitor Resource Usage
Regularly use pm2 monit to observe memory and CPU usage. Set up alerts for abnormal spikes. High memory usage may indicate leaks; high CPU may suggest inefficient code or insufficient instances.
Use Non-Root User for Security
Never run PM2 as the root user. Create a dedicated system user (e.g., nodeapp) and run PM2 under that account:
sudo adduser nodeapp
sudo usermod -aG sudo nodeapp
su - nodeapp
pm2 start app.js
This minimizes the risk of privilege escalation if your application is compromised.
Enable Error Handling and Graceful Shutdown
Improve application resilience by handling uncaught exceptions and signals in your Node.js code:
process.on('uncaughtException', (err) => {
console.error('Uncaught Exception:', err);
process.exit(1);
});
process.on('SIGTERM', () => {
console.log('SIGTERM received. Shutting down gracefully...');
server.close(() => {
console.log('Server closed.');
process.exit(0);
});
});
PM2 respects these signals and will wait for your app to shut down cleanly before killing the process.
Regularly Update PM2
Keep PM2 updated to benefit from performance improvements and security patches:
npm install -g pm2@latest
After updating, restart your apps to ensure compatibility:
pm2 restart all
Tools and Resources
PM2 Monitoring Dashboard (PM2 Plus)
While the CLI is powerful, PM2 offers a cloud-based monitoring solution called PM2 Plus (now part of Keymetrics). It provides:
- Real-time dashboards with CPU, memory, and request metrics
- Alerts for high load, crashes, or memory leaks
- Log aggregation across multiple servers
- Deployment tracking and rollback
- Team collaboration features
To enable PM2 Plus, sign up at https://app.keymetrics.io, then link your server:
pm2 link <public-key> <private-key>
Its free for up to 3 servers and 5 appsideal for small teams and startups.
PM2 Logrotate
As mentioned earlier, pm2-logrotate is an essential module for managing log files. It prevents disk space exhaustion and simplifies log analysis.
PM2 Startup Scripts
PM2 generates init scripts for systemd, upstart, and launchd. Always use pm2 startup instead of manually writing service files to ensure compatibility across Linux distributions.
Third-Party Integrations
PM2 integrates seamlessly with:
- Docker: Run PM2 inside containers for orchestration with Kubernetes or Docker Compose.
- Nginx: Use Nginx as a reverse proxy in front of multiple PM2-managed apps for load balancing.
- CI/CD Pipelines: Automate deployments using GitHub Actions, GitLab CI, or Jenkins with
pm2 deploy. - System Monitoring Tools: Export metrics to Prometheus, Grafana, or Datadog using custom exporters.
Documentation and Community
Official documentation is available at https://pm2.keymetrics.io/. The community is active on GitHub and Stack Overflow. Always refer to the official docs for the latest features and syntax.
VS Code Extensions
Install the PM2 for VS Code extension to manage PM2 processes directly from your IDE. It provides a visual interface for starting, stopping, and viewing logs without leaving your editor.
Real Examples
Example 1: Express.js API Server
Consider a simple Express.js application:
// app.js
const express = require('express');
const app = express();
const PORT = process.env.PORT || 3000;
app.get('/', (req, res) => {
res.json({ message: 'Hello from PM2!' });
});
app.listen(PORT, () => {
console.log(Server running on port ${PORT});
});
Configuration file (ecosystem.config.js):
module.exports = {
apps: [{
name: 'express-api',
script: './app.js',
instances: 'max',
exec_mode: 'cluster',
autorestart: true,
watch: false,
max_memory_restart: '1G',
env: {
NODE_ENV: 'development',
PORT: 3000
},
env_production: {
NODE_ENV: 'production',
PORT: 8080
},
log: '/var/log/express-api/output.log',
error: '/var/log/express-api/error.log'
}]
};
Deployment steps:
- Run
pm2 start ecosystem.config.js --env production - Run
pm2 startupand execute the suggested sudo command - Run
pm2 save - Set up Nginx to proxy requests to port 8080
Example 2: Multiple Microservices
Manage multiple services with a single ecosystem file:
module.exports = {
apps: [
{
name: 'auth-service',
script: './services/auth/app.js',
instances: 2,
exec_mode: 'cluster',
env_production: { NODE_ENV: 'production', DB_URL: 'mongodb://auth-db:27017/auth' }
},
{
name: 'user-service',
script: './services/user/app.js',
instances: 2,
exec_mode: 'cluster',
env_production: { NODE_ENV: 'production', DB_URL: 'mongodb://user-db:27017/users' }
},
{
name: 'notification-service',
script: './services/notification/app.js',
instances: 1,
exec_mode: 'fork',
env_production: { NODE_ENV: 'production', WEBHOOK_URL: 'https://webhook.example.com' }
}
]
};
Start all with one command:
pm2 start ecosystem.config.js --env production
Monitor each individually:
pm2 monit
pm2 logs auth-service
pm2 restart user-service
Example 3: Docker + PM2
Run PM2 inside a Docker container for containerized deployments:
Dockerfile
FROM node:18-alpine
WORKDIR /app
COPY package*.json ./
RUN npm install --only=production
COPY . .
Install PM2 globally
RUN npm install -g pm2
Expose port
EXPOSE 3000
Start with PM2
CMD ["pm2-start", "ecosystem.config.js"]
Build and run:
docker build -t my-node-app .
docker run -d -p 3000:3000 --name myapp my-node-app
Use this approach with Docker Compose for multi-container apps.
FAQs
Is PM2 better than nodemon?
PM2 and nodemon serve different purposes. Nodemon is a development tool that restarts your app on file changes. PM2 is a production process manager with clustering, logging, monitoring, and auto-restart. Use nodemon during development and PM2 in production.
Can PM2 manage non-Node.js applications?
Yes. PM2 can manage any executable, including Python scripts, Ruby apps, or shell scripts. For example: pm2 start script.py --name "python-app". However, Node.js-specific features like cluster mode and memory monitoring are only available for Node.js apps.
Does PM2 consume a lot of system resources?
No. PM2 is lightweight. The main process (PM2 daemon) uses minimal memory (typically 1030 MB). The overhead is negligible compared to the benefits it provides in stability and scalability.
How do I upgrade PM2 without downtime?
Upgrade PM2 globally with npm install -g pm2@latest. Then, restart your apps with pm2 restart all. Since PM2 manages your apps, your services remain online during the upgrade.
Why does my app restart every few minutes?
This usually indicates a crash loop. Check logs with pm2 logs. Common causes: unhandled exceptions, missing environment variables, port conflicts, or database connection failures. Use max_restarts: 5 to prevent infinite restarts.
Can I use PM2 on Windows?
Yes, but with limitations. PM2 works on Windows, but cluster mode and auto-start features are not fully supported. For Windows production environments, consider using Windows Services or Docker.
How do I check which apps are running?
Use pm2 list to see all managed apps and their status. Use pm2 show <name> for detailed configuration and metrics.
Is PM2 secure?
PM2 is secure when used correctly. Always run it under a non-root user, avoid exposing the PM2 dashboard to the public internet, and keep PM2 updated. Never store secrets in plain text config filesuse environment variables or secrets managers.
Can I use PM2 with serverless functions?
Not directly. PM2 is designed for long-running processes. Serverless platforms (AWS Lambda, Vercel, Netlify) are stateless and ephemeral. Use PM2 for traditional servers and serverless for event-driven workloads.
What happens if PM2 crashes?
PM2 is designed to be resilient. If the PM2 daemon crashes, your apps continue running. You can restart PM2 with pm2 resurrect to restore the previous process list. However, if the entire server reboots, you must have run pm2 startup and pm2 save to auto-recover.
Conclusion
Managing Node.js applications in production is not just about writing clean codeits about ensuring uptime, performance, and resilience. PM2 is not merely a tool; its a necessity for any serious Node.js deployment. From automatic restarts and cluster mode scaling to log management and zero-downtime deployments, PM2 eliminates the manual, error-prone tasks that can derail even the most well-designed applications.
This guide has walked you through every critical aspect of using PM2: from installation and configuration to monitoring, deployment, and best practices. Whether youre running a single API endpoint or a complex microservices architecture, PM2 gives you the control and reliability needed to operate at scale.
Remember: never run a production Node.js app without a process manager. Start with the ecosystem.config.js file, enable cluster mode, set memory limits, and configure auto-start. Combine PM2 with logging tools, monitoring dashboards, and CI/CD pipelines to create a robust, production-ready infrastructure.
As Node.js continues to dominate backend development, mastering PM2 will not only improve your applications stability but also elevate your skills as a developer or DevOps engineer. Invest the time to implement these practices todayyour users, your team, and your server bills will thank you tomorrow.