Running a Node.js app with node app.js works fine until the process crashes at 2 a.m., or you need to restart it without dropping active connections, or you're juggling five services on one server and tailing five separate log files. PM2 was built to remove that friction: it's an open-source process manager, with over 100 million downloads and more than a decade of active development, that keeps Node.js (and non-Node) processes alive, load-balanced, and logged in one place.
This guide covers what PM2 actually does, how to install and run it on an AWS EC2 instance, the commands you'll use daily, and just as important where PM2's job ends and a different tool (Docker, systemd, a managed PaaS) should take over.
What is PM2?
PM2 is a process manager for Node.js applications that keeps processes running in the background, typically in a production environment, and recovers them automatically when they crash. It wraps your app in a daemon ("God" process in PM2's own terminology) that supervises it: starting, stopping, restarting, and reporting on every process it manages.
Key features of PM2
Process management. Start, stop, restart, and delete processes from one CLI, and manage multiple apps from the same process list without separate terminal sessions for each.
Load balancing. Cluster mode spins up multiple instances of the same app across CPU cores and distributes incoming traffic between them, using Node's built-in cluster module under the hood.
Logging and monitoring. pm2 logs streams combined output from every managed process; pm2 monit opens a live CPU/memory dashboard in the terminal without installing anything extra.
Automatic restart. PM2 restarts a crashed process by default. You can also cap restarts with --max-restarts or set --max-memory-restart 300M to restart a process that leaks past a memory ceiling useful for catching slow leaks before they take down a box.
Startup scripts. pm2 startup generates an OS-specific script (systemd, upstart, etc.) so your managed processes come back automatically after a server reboot.
Ecosystem configuration files. PM2 supports ecosystem.config.js (the documented, preferred format), plus JSON or YAML, for declaring every app's settings script path, instances, env vars, log file locations in one version-controlled file instead of long CLI commands.
Why use PM2?
PM2 earns its place in production Node.js deployments for a few concrete reasons:
- It restarts your app automatically on a crash, and can reload it with zero downtime when you deploy new code via
pm2 reload. - It gives you a single dashboard-style view (
pm2 monit,pm2 list) of memory, CPU, and status across every process on the box — a lightweight alternative to standing up a separate monitoring stack for a small deployment. - It manages multiple Node.js apps on the same server from one CLI, which matters once you're running more than a single service per VM.
- It aggregates logs from every managed process into one place, so
pm2 logsreplaces tailing five separate files. - It distributes traffic across CPU cores in cluster mode, letting a single Node process use hardware it otherwise couldn't (Node itself is single-threaded per process).
- It has a large, active community and 12+ years of maintenance behind it, so most operational questions already have a documented answer.
How to Install PM2 with Node on AWS EC2
Steps vary slightly by EC2 operating system (Amazon Linux vs. Ubuntu); both are covered below.
Step 1: Connect to your EC2 instance
Use SSH, with the default user depending on the AMI:
- Amazon Linux:
ec2-user - Ubuntu:
ubuntu
ssh -i your-key.pem ec2-user@your-ec2-instance
Replace your-key.pem with your key file and your-ec2-instance with the instance's public IP or DNS.
Step 2: Install Node.js and npm
Install a current LTS release (Node 20 or later).
For Amazon Linux 2 / 2023:
sudo yum update -y
curl -fsSL https://rpm.nodesource.com/setup_20.x | sudo bash -
sudo yum install -y nodejs
For Ubuntu:
sudo apt-get update
curl -fsSL https://deb.nodesource.com/setup_20.x | sudo -E bash -
sudo apt-get install -y nodejs
Verify:
node -v
npm -v
Step 3: Install PM2
sudo npm install pm2 -g
pm2 -v
Step 4: Start your Node.js application
cd /path/to/your/app
pm2 start app.js
To enable load balancing in cluster mode across all available CPU cores:
pm2 start app.js -i max
Step 5: Set up automatic startup on reboot
pm2 startup
Copy and run the generated command, it registers PM2 with your OS's init system (systemd on most modern Amazon Linux/Ubuntu AMIs).
Step 6: Save the process list
pm2 save
This writes the current list to $HOME/.pm2/dump.pm2 so pm2 resurrect (or the startup hook) can bring every process back after a reboot.
Security note: Run PM2 as a non-root user (ec2-user or ubuntu), restrict your AWS security group to the ports you actually need (80, 443, 22), and rotate your SSH key periodically.
How to List and Inspect Processes in PM2
pm2 list
Shows every managed process with its name, PID, status, restart count, CPU, and memory.
Filter or sort a longer list:
pm2 list --sort memory
pm2 list --filter app
For full detail on one process:
pm2 describe app_name
Common PM2 Commands
| Command | Description |
|---|---|
pm2 start app.js | Start an application |
pm2 start app.js --name my-app | Start and give it a readable name |
pm2 list | List all managed processes |
pm2 stop app_name | Stop a running app by name or ID |
pm2 restart app_name | Restart an app (brief downtime) |
pm2 reload app_name | Zero-downtime reload (cluster mode only) |
pm2 delete app_name | Stop and remove an app from the list |
pm2 logs | Stream logs for all apps |
pm2 logs app_name --lines 200 | Show the last 200 log lines for one app |
pm2 flush | Clear all log files |
pm2 monit | Open the live CPU/memory monitoring dashboard |
pm2 save | Persist the current process list to disk |
pm2 resurrect | Restore a previously saved process list |
Log Management and Environment Variables
By default, PM2 writes separate stdout and stderr files per process under ~/.pm2/logs/. You can override the paths explicitly:
pm2 start app.js -o ./logs/out.log -e ./logs/error.log
For environment-specific config (staging vs. production), define named environments inside the ecosystem file rather than exporting variables by hand on each server it keeps the difference between environments in version control instead of in someone's shell history.
Using PM2 with Non-Node.js Applications
PM2 isn't limited to Node, it supervises any process via a custom interpreter flag:
pm2 start script.py --interpreter python3
This is handy for small Python or Ruby worker scripts that need the same restart/logging behavior as your Node services, without adopting a separate process manager just for them.
Configuration with Ecosystem Files
For anything beyond a single app, an ecosystem.config.js file replaces long CLI invocations with a single declarative source of truth:
module.exports = {
apps: [
{
name: 'my-app',
script: 'app.js',
instances: 'max',
exec_mode: 'cluster',
env: {
NODE_ENV: 'development',
},
env_production: {
NODE_ENV: 'production',
PORT: 3000,
},
max_memory_restart: '300M',
error_file: './logs/error.log',
out_file: './logs/out.log',
},
],
};
Start it with:
pm2 start ecosystem.config.js --env production
Because it's a plain JS/JSON/YAML file, it belongs in your repo next to the app it configures code review catches a bad restart policy or a missing env var before it reaches production, the same as any other config change.
When PM2 Isn't the Right Tool
PM2 is built for a single server or a small, manually managed fleet of EC2 instances. It's worth knowing where that stops making sense:
- Multi-server orchestration, autoscaling, and rolling deployments across many hosts are jobs for Docker + Kubernetes, ECS, or a managed PaaS — PM2 has no concept of "another server."
- Inside a Docker container, you generally don't need PM2's restart supervision at all, since the container orchestrator (Kubernetes, ECS) already restarts failed containers; running PM2 inside the container usually just adds an unnecessary layer, though some teams still use it for in-container cluster mode on multi-core instances.
- Serverless/FaaS deployments (Lambda, Cloud Functions) don't run long-lived processes, so PM2 doesn't apply.
If you're already running Kubernetes or a serverless platform, PM2 is solving a problem you likely don't have.
How to Choose: PM2 vs. the Alternatives
- Is this one VM/EC2 instance, or a cluster of servers? One or a handful of manually managed instances: PM2 fits well. A cluster with autoscaling: look at Kubernetes or ECS instead.
- Do you need zero-downtime reloads? PM2's
reloadcommand (cluster mode) handles this natively for a single-host deployment without extra tooling. - Is monitoring beyond CPU/memory a requirement (distributed tracing, alerting, APM)? PM2's built-in
monitis a terminal dashboard, not a full observability stack pair it with a dedicated APM tool if you need that depth. - Will this run inside a container? If yes, check whether your orchestrator's own restart policy already covers what PM2 would do before adding it as a second layer.
Need Help Deploying and Scaling Your Node.js App?
Choosing between PM2, containers, and a managed platform depends on your traffic patterns, team size, and how much ops overhead you want to own. Hire Node.js developers at Lucent Innovation to design a deployment that matches where your app actually is today,not a more complex setup than you need yet.


