Node.js is an open-source JavaScript runtime built on Chrome's V8 engine, known for its speed and scalability in real-time and high-performance applications. Running Node applications in production comes with unique challenges — you need to handle unexpected crashes, manage processes, and ensure continuous uptime. PM2 is a production process manager for Node.js applications that simplifies this, letting you monitor, restart, and optimize your apps. This guide walks through installing PM2, running a sample Node.js app under it, and configuring PM2 for production use. By the end, you'll have a Node.js application managed by PM2 with automatic restarts, centralized logs, and startup persistence configured.
Prerequisites
- Access to your workstation as a non-root sudo user, running macOS, Linux, or Windows, with Node and npm installed.
Install PM2 Using npm
1. Install PM2 via the npm package manager:
$ sudo npm install pm2 -g
Create an Example Node.js Application
1. Navigate to your home directory:
$ cd ~
2. Create a file named app.js using a text editor such as vim:
$ vim app.js
3. Add the following code to the file:
const http = require('http');
const hostname = '0.0.0.0';
const port = 3000;
const server = http.createServer((req, res) => {
res.statusCode = 200;
res.setHeader('Content-Type', 'text/plain');
res.end('Hello World');
});
server.listen(port, hostname, () => {
console.log(`Server running at http://${hostname}:${port}/`);
});
Save and exit the file. This example app listens on port 3000 and responds to HTTP requests with the message "Hello World".
Start the Application Using PM2
1. Start your Node.js application with PM2 (replace app.js with your entry file if needed):
$ pm2 start app.js
Your output should look similar to:
[PM2] Starting /home/linuxuser/app.js in fork_mode (1 instance)
[PM2] Done.
┌────┬────────────────────┬──────────┬──────┬───────────┬──────────┬──────────┐
│ id │ name │ mode │ ↺ │ status │ cpu │ memory │
├────┼────────────────────┼──────────┼──────┼───────────┼──────────┼──────────┤
│ 0 │ app │ fork │ 0 │ online │ 0% │ 4.4mb │
└────┴────────────────────┴──────────┴──────┴───────────┴──────────┴──────────┘
Useful additional parameters when starting an app:
-
--name <app_name>- specify an application name -
--watch- restart your application automatically when a file changes -
--max-memory-restart <memory>- a memory limit that triggers an automatic restart when reached -
--log <log_file>- specify a log file -
--restart-delay <delay>- delay between automatic restarts in milliseconds -
--time- prefix logs with time -
--no-autorestart- turn off automatic application restarts -
--cron- a cron job pattern for automatic application restarts -
--no-daemon- do not run the application in a daemon process
Visit the official documentation to view all available parameters.
Manage the Application
1. Restart your PM2-managed application:
$ pm2 restart app
2. Reload your PM2-managed application:
$ pm2 reload app
3. Stop your PM2-managed application:
$ pm2 stop app
4. Delete your PM2-managed application:
$ pm2 delete app
List All Applications
1. List all the applications managed by PM2:
$ pm2 list
Display Logs
1. View the logs produced by your application in real time:
$ pm2 logs
2. View older logs by specifying the number of lines with the --lines flag:
$ pm2 logs --lines 200
Monitor Resource Usage
1. Monitor the resources consumed by your applications in near real time:
$ pm2 monit
Set Up a Web-Based Dashboard
1. Configure a web-based PM2 dashboard:
$ pm2 plus
Follow the prompts to create or log in to a PM2 account. If you don't have one, complete the required information and accept the license agreement. You'll see output during setup similar to:
[PM2 I/O] Do you have a pm2.io account? (y/n) n
[PM2 I/O] No problem! We just need a few details to create your account.
[PM2 I/O] Please choose a username: exampleuser
[PM2 I/O] Please choose an email: admin@example.com
[PM2 I/O] Please choose a password: ************
...
[PM2 I/O] Do you accept the terms and privacy policy (https://pm2.io/legals/terms_conditions.pdf)? (y/n) y
[PM2 I/O] Successfully authenticated
[PM2 I/O] Successfully validated
[+] PM2+ activated!
[PM2 I/O] Successfully connected to bucket PM2 Plus Monitoring
[PM2 I/O] You can use the web interface here: https://app.pm2.io/#/bucket/67cb27ccd623d57f6d4c63c0
Replace exampleuser with your preferred username, admin@example.com with your login email address, and provide a strong password to secure your PM2 account. Then open the provided web address, log in with your PM2 account credentials, and start monitoring your applications through the PM2 Plus dashboard.
PM2 Plus is a subscription-based offering that incurs a cost depending on the number of processes you want to monitor. Review the pricing details on the PM2 Plus page.
Configure PM2 to Start on Server Boot
1. Generate a startup script and configure PM2 to start on server boot:
$ pm2 startup
Your output should look similar to:
[PM2] To setup the Startup Script, copy/paste the following command:
sudo env PATH=$PATH:/home/linuxuser/.nvm/versions/node/v22.14.0/bin /home/linuxuser/.nvm/versions/node/v22.14.0/lib/node_modules/pm2/bin/pm2 startup systemd -u linuxuser --hp /home/linuxuser
2. Copy the command from the previous output and run it to make the PM2 process persistent:
$ sudo env PATH=$PATH:/home/linuxuser/.nvm/versions/node/v22.14.0/bin /home/linuxuser/.nvm/versions/node/v22.14.0/lib/node_modules/pm2/bin/pm2 startup systemd -u linuxuser --hp /home/linuxuser
Your output should look similar to:
...
[PM2] Writing init configuration in /etc/systemd/system/pm2-linuxuser.service
Created symlink /etc/systemd/system/multi-user.target.wants/pm2-linuxuser.service → /etc/systemd/system/pm2-linuxuser.service.
...
Configure Applications to Start on Server Boot
1. Save the running applications to the list:
$ pm2 save
Your output should look similar to:
[PM2] Saving current process list...
[PM2] Successfully saved in /home/linuxuser/.pm2/dump.pm2
2. Restore the saved applications manually from the list if needed:
$ pm2 resurrect
Your output should look similar to:
[PM2] Resurrecting
[PM2] Restoring processes located in /home/linuxuser/.pm2/dump.pm2
[PM2] Process /home/linuxuser/app.js restored
┌────┬────────────────────┬──────────┬──────┬───────────┬──────────┬──────────┐
│ id │ name │ mode │ ↺ │ status │ cpu │ memory │
├────┼────────────────────┼──────────┼──────┼───────────┼──────────┼──────────┤
│ 0 │ app │ fork │ 0 │ online │ 0% │ 21.3mb │
└────┴────────────────────┴──────────┴──────┴───────────┴──────────┴──────────┘
Check for Updates
1. Print a list of outdated npm packages on your system:
$ npm outdated -g
This displays a list of globally installed npm packages that have newer versions available.
Update PM2
1. Update the PM2 package via npm (this stops all running PM2 processes until the upgrade completes, causing downtime):
$ npm install pm2@latest -g
2. Perform an in-memory update of PM2:
$ pm2 update
Best Practices and Security Considerations
Prevent Downtime With Cluster Mode
Your PM2 processes may restart multiple times during their lifecycle, causing temporary downtime. Cluster mode runs multiple instances of your application, and when a restart is required, only one instance stops and restarts at a time while the others keep serving traffic.
1. Delete the application before switching to cluster mode:
$ pm2 delete app
2. Start the application in cluster mode, specifying the number of instances with the -i parameter:
$ pm2 start app.js -i 3
This starts three instances of your application in cluster mode using PM2.
3. Scale the application by specifying the new number of instances:
$ pm2 scale app 4
This scales your app application up to 4 instances.
Eliminate Failed Requests With Graceful Shutdown
PM2 ensures graceful shutdowns by sending signals to your application so it can terminate cleanly, helping prevent data loss or corruption by allowing your app to finish active tasks before exiting:
- Before shutdown, PM2 sends a
SIGINTsignal to your application. - Your application intercepts the signal.
- It finishes active requests and closes open resources like database connections.
- The application exits.
1. Add the following code to enable graceful shutdown in your application:
process.on('SIGINT', function() {
// sigint signal received, log a message to the console
console.log('Shutdown signal intercepted');
// close the http server
server.close();
// exit the process
process.exit();
});
This intercepts the SIGINT signal, logs a message to the console, closes the HTTP server, and exits the process cleanly.
Next Steps
- Enable cluster mode in production to eliminate downtime during restarts
- Set up PM2 Plus (or another monitoring tool) for centralized visibility across multiple servers
- Add graceful shutdown handling to any application that holds open connections or resources
- Explore PM2's ecosystem file (
pm2.config.js) to manage multiple apps and environments from one file
For the full guide with additional tips, visit the original article on Vultr Docs.
Top comments (0)