When we build a Node.js or MERN Stack application locally, we usually start the backend with a command such as: npm run dev or: npm start The application st
MSMuhammad SufiyanSoftware Engineer · Jul 25
Backend Engineering HubT-
When we build a Node.js or MERN Stack application locally, we usually start the backend with a command such as:
npm run dev
or:
npm start
The application starts, the terminal displays:
Server running on port 3000
Database connected successfully
Everything appears to be working perfectly.
So why do developers use PM2?
Why not simply run npm start on the production server?
That is exactly what we will understand in this guide.
By the end, you will know:
What PM2 is
Why PM2 is used
How PM2 differs from npm start
How to manage applications with PM2
How PM2 handles crashes and server restarts
How to create an ecosystem configuration file
How PM2 cluster mode works
How to perform graceful and zero-downtime reloads
How to use PM2 on an AWS EC2 server
Whether PM2 should be used with Docker
Common PM2 errors and their solutions
1. What Is PM2?
PM2 is a production process manager.
A process manager is a tool that starts, stops, monitors and controls running applications.
In simple words:
PM2 does not build your Node.js application. It keeps your running application manageable and available.
PM2 can:
Run an application in the background
Restart an application after a crash
Show application logs
Display CPU and memory usage
Restart applications after a server reboot
Run multiple application instances
Perform zero-downtime reloads
Apply memory-based and scheduled restart rules
The official PM2 documentation describes it as a daemon process manager with monitoring, startup scripts, load balancing and zero-downtime reload capabilities.
2. npm start Is Not Wrong
A common misunderstanding is:
We use PM2 because npm start is bad.
That is incorrect.
npm start is perfectly valid.
Suppose your package.json contains:
{
"scripts": {
"start": "node server.js"
}
}
When you execute:
npm start
npm runs:
node server.js
Your application starts successfully.
The difference is not primarily about how the application starts.
The difference is about what happens after the application starts.
3. npm start vs PM2
Consider this simple difference:
Using npm start
Start the application
Using PM2
Start the application
+
Keep it running in the background
+
Monitor it
+
Store its logs
+
Restart it after crashes
+
Restore it after a server reboot
A useful sentence to remember is:
npm start starts your application. PM2 manages the running application.
4. Why Is PM2 Needed?
Let us understand the problems one by one.
Problem 1: The Application Is Attached to the Terminal
Imagine that you connect to an AWS EC2 server:
ssh -i server-key.pem ubuntu@your-server-ip
You open the project:
cd backend
You start the application:
npm start
The API becomes available:
http://your-server-ip:3000
However, that Node.js process is running inside your current terminal session.
Depending on how the process and shell are configured, closing the SSH session can terminate the application.
Even when it remains alive through another shell technique, you still do not have proper process management, monitoring or restart handling.
With PM2, you can run:
pm2 start server.js --name backend-api
PM2 runs and manages the application as a background process. PM2’s process-management commands can start, stop, restart, reload and list applications running in the background.
You can now close the SSH terminal and reconnect later.
Check the application:
pm2 status
The application should still be running:
backend-api online
Problem 2: The Application Can Crash
Suppose an unhandled error occurs:
throw new Error("Unexpected application error");
When running normally:
npm start
the Node.js process may exit.
Your application is now unavailable until someone manually starts it again.
npm start
With PM2:
pm2 start server.js --name backend-api
If the process exits unexpectedly, PM2 automatically attempts to start it again. Automatic restart after an application crash or exit is PM2’s default behavior.
The flow becomes:
Application crashes
↓
Node.js process exits
↓
PM2 detects the exit
↓
PM2 starts a new process
PM2 does not fix the programming error.
It only restores the process.
PM2 handles recovery. The developer must still fix the actual bug.
Problem 3: The Server Can Reboot
Suppose the EC2 machine restarts because of:
A manual reboot
Server maintenance
An operating system update
An unexpected machine failure
After the machine starts again, your Node.js process will not automatically return simply because you had previously run:
npm start
PM2 can generate an operating system startup service:
pm2 startup
PM2 prints another command. Copy and execute the exact command displayed in your terminal.
Then save the current PM2 process list:
pm2 save
PM2 can use the generated startup script and saved process list to restore managed applications after a machine reboot.
The complete idea is:
Server reboots
↓
Operating system starts PM2
↓
PM2 reads the saved process list
↓
PM2 starts the applications
Problem 4: We Need Application Logs
When an application runs normally, its logs are displayed in the terminal:
Database connected
Server started
User logged in
Payment service failed
Once that terminal is gone, inspecting previous output becomes less convenient unless another logging solution has been configured.
With PM2:
pm2 logs
For one application:
pm2 logs backend-api
Last 100 lines:
pm2 logs backend-api --lines 100
Only error logs:
pm2 logs backend-api --err
PM2 stores process output and error log files under:
$HOME/.pm2/logs
PM2 officially provides live log streaming and stores application logs in the user’s .pm2/logs directory.
Problem 5: We Need to Monitor the Application
PM2 can display the current state of managed processes:
pm2 status
Example:
name status cpu memory uptime restarts
backend-api online 1% 92 MB 2h 0
This helps us answer:
Is the application online?
How much memory is it using?
How much CPU is it using?
How long has it been running?
How many times has it restarted?
For an interactive terminal monitor:
pm2 monit
PM2’s standard workflow includes process status, logs and runtime metrics.
5. Building a Practical PM2 Project
Let us create a small Express application to test PM2.
Create the project
mkdir pm2-practical
cd pm2-practical
npm init -y
npm install express
Create a file named:
server.js
Add the following code:
const express = require("express");
const app = express();
const PORT = process.env.PORT || 3000;
app.get("/", (req, res) => {
res.json({
message: "PM2 practical API is running",
processId: process.pid,
environment: process.env.NODE_ENV || "development",
uptime: process.uptime(),
time: new Date().toISOString(),
});
});
app.get("/health", (req, res) => {
res.status(200).json({
status: "healthy",
processId: process.pid,
uptime: process.uptime(),
});
});
// Classroom demonstration only
app.get("/crash", (req, res) => {
res.json({
message: "The application will crash after one second",
});
setTimeout(() => {
throw new Error("Intentional classroom crash");
}, 1000);
});
const server = app.listen(PORT, () => {
console.log(`Server running on port ${PORT}`);
console.log(`Process ID: ${process.pid}`);
});
function gracefulShutdown(signal) {
console.log(`${signal} received. Starting graceful shutdown...`);
server.close(() => {
console.log("HTTP server closed");
process.exit(0);
});
setTimeout(() => {
console.error("Graceful shutdown timed out");
process.exit(1);
}, 10000).unref();
}
process.on("SIGINT", () => gracefulShutdown("SIGINT"));
process.on("SIGTERM", () => gracefulShutdown("SIGTERM"));
Update package.json:
{
"scripts": {
"start": "node server.js"
}
}
Run it normally:
npm start
Open:
http://localhost:3000
Stop it with:
Ctrl + C
The application immediately stops.
That is normal because no process manager is managing it.
6. Installing PM2
Install PM2 globally:
npm install pm2@latest -g
Check the version:
pm2 --version
Check the current process list:
pm2 status
7. Starting the First Application
Start the Express application:
pm2 start server.js
PM2 will assign a default application name.
A better approach is to provide a meaningful name:
pm2 start server.js --name backend-api
Check its status:
pm2 status
You should see something similar to:
id name mode status cpu memory
0 backend-api fork online 0% 45 MB
8. Essential PM2 Commands
List all applications
pm2 list
or:
pm2 status
View detailed information
pm2 describe backend-api
You can also use the PM2 process ID:
pm2 describe 0
Restart the application
pm2 restart backend-api
Stop the application
pm2 stop backend-api
Stopping keeps the application inside PM2’s process list, but the process is no longer running.
Start a stopped application
pm2 start backend-api
Delete the application
pm2 delete backend-api
Deleting stops the application and removes it from the PM2 process list.
Manage all applications
pm2 restart all
pm2 stop all
pm2 delete all
PM2 accepts application names, IDs or all for standard lifecycle operations.
PM2 cluster mode uses Node.js clustering to run multiple application processes and distribute supported network connections among them.
21. Practical Cluster Demonstration
Delete the existing process:
pm2 delete backend-api
Start two instances:
pm2 start server.js --name backend-api -i 2
Check:
pm2 status
You should see two processes with the same application name.
Now repeatedly call:
curl http://localhost:3000
The response includes:
{
"message": "PM2 practical API is running",
"processId": 12430
}
Another request may return:
{
"message": "PM2 practical API is running",
"processId": 12437
}
Different process IDs indicate that different workers handled the requests.
22. The Most Important Cluster-Mode Rule
Clustered applications should be stateless.
Avoid storing important shared data only in process memory:
let loggedInUsers = [];
let shoppingCart = [];
let verificationCodes = {};
Why?
Because every process has separate memory.
Process 1 memory ≠ Process 2 memory
A request might store data in Process 1, while the next request is handled by Process 2.
Shared application data should normally be stored in systems such as:
MongoDB
PostgreSQL
Redis
Shared object storage
A queue or external service
The PM2 cluster documentation specifically warns against keeping local session or application state inside one process when multiple instances are being used.
23. Scaling a Running Application
Scale to four instances:
pm2 scale backend-api 4
Add two instances:
pm2 scale backend-api +2
Remove one instance:
pm2 scale backend-api -1
Do not always use:
-i max
without thinking.
Your server also needs resources for:
The operating system
Nginx
Databases
Redis
Background workers
Monitoring tools
On a small server, one or two application instances may be more suitable than using every available CPU core.
24. Restart vs Reload
These two commands are not identical.
Restart
pm2 restart backend-api
Conceptually:
Stop old process
↓
Start new process
A brief interruption may occur.
Reload
pm2 reload backend-api
In cluster mode, PM2 can start replacement workers and retire old workers after the new ones are available.
Start new worker
↓
New worker becomes available
↓
Stop old worker
PM2 documents reload as a zero-downtime operation for cluster-mode applications, whereas restart kills and starts the process again.
A simple rule:
Fork mode → restart
Cluster mode → reload
25. startOrReload for Deployment
During deployment, you may not know whether the application is already running.
Use:
pm2 startOrReload ecosystem.config.js --env production
It behaves like this:
Application is not running
↓
Start it
Application is already running
↓
Reload it
This makes the same deployment command useful for both the first deployment and future updates.
PM2 officially recommends startOrReload for idempotent deployment workflows.
26. Graceful Shutdown
Suppose your application receives a request to stop.
It may still have:
Active HTTP requests
Open database connections
Redis connections
Queue jobs
File operations
Pending messages
Immediately terminating the process can interrupt these operations.
A graceful shutdown means:
Stop accepting new work
↓
Complete or close existing work
↓
Close external connections
↓
Exit the process
In a simple Docker architecture, the recommended model is usually:
One main Node.js process
↓
One container
↓
Docker manages the container lifecycle
Therefore:
If Docker is already managing your Node.js application, PM2 is usually unnecessary.
35. Can PM2 Be Used Inside Docker?
Yes.
PM2 provides a container-oriented command called:
pm2-runtime
Example Dockerfile:
FROM node:22-alpine
WORKDIR /app
COPY package*.json ./
RUN npm ci --omit=dev
RUN npm install pm2 -g
COPY . .
EXPOSE 3000
CMD ["pm2-runtime", "server.js"]
PM2’s official Docker integration recommends pm2-runtime rather than the normal background daemon approach when PM2 is used inside a container. It keeps PM2 in the foreground and forwards shutdown signals to the application.
However, do not add PM2 to every Docker container without a reason.
Possible reasons to use it include:
You specifically need PM2 monitoring features
You intentionally run multiple Node.js processes in one container
You require PM2’s process configuration
Your organization has standardized around PM2 Runtime
For most beginner Docker deployments:
CMD ["node", "server.js"]
or:
CMD ["npm", "start"]
with a Docker restart policy is simpler.
36. PM2 vs Docker: The Final Rule
Use this decision:
Running Node.js directly on a VM or EC2?
↓
PM2 is useful
Running Node.js inside Docker?
↓
Usually use Docker lifecycle management
Using Kubernetes, ECS, Render or another managed platform?
↓
Usually let the platform manage process/container restarts
Learn how to inspect application behavior without directly watching the original terminal.
Lab 4: Ecosystem Configuration
Create:
ecosystem.config.js
Add:
Application name
Production environment
Restart delay
Memory limit
Log date format
Run:
pm2 start ecosystem.config.js --env production
Objective:
Move from command-based configuration to reusable production configuration.
Lab 5: Cluster Mode
Start two instances:
pm2 start server.js --name student-api -i 2
Call the API repeatedly:
curl http://localhost:3000
Compare process IDs.
Then scale:
pm2 scale student-api 4
Objective:
Understand multiple Node.js processes and stateless applications.
Lab 6: Restart vs Reload
Start the application in cluster mode.
Run continuous requests:
while true
do
curl -s http://localhost:3000
echo
sleep 0.5
done
In another terminal:
pm2 reload student-api
Objective:
Observe how cluster workers can be replaced without a hard application restart.
Lab 7: EC2 Reboot Recovery
On AWS EC2:
pm2 startup
Execute the generated command:
pm2 save
sudo reboot
Reconnect:
pm2 status
Objective:
Confirm that the application returns automatically after a server reboot.
40. Final Student Assignment
Deploy an Express or NestJS backend on AWS EC2 without Docker.
Requirements:
1. Clone the project on EC2. 2. Install production dependencies. 3. Create production environment variables. 4. Install PM2. 5. Create an ecosystem file. 6. Run the application with a meaningful name. 7. Configure automatic restart. 8. Configure a restart delay. 9. Configure a memory limit. 10. Implement graceful shutdown. 11. Run two cluster instances. 12. Create a /health endpoint. 13. Configure PM2 startup. 14. Save the PM2 process list. 15. Reboot EC2 and verify recovery. 16. Perform a deployment using startOrReload. 17. Install log rotation. 18. Document all commands in the project README.
Bonus tasks:
Add Nginx as a reverse proxy
Configure a domain
Configure HTTPS
Add a separate BullMQ worker
Create a GitHub Actions deployment
Store shared cluster state in Redis
Add structured production logging
41. PM2 Interview Questions
What is PM2?
PM2 is a process manager used to run, monitor and manage Node.js applications in production.
Why not only use npm start?
npm start starts the application. It does not, by itself, provide PM2-style background process management, crash recovery, monitoring, stored logs or reboot restoration.
What is the difference between stop and delete?
stop stops the process but keeps it in PM2’s list.
delete stops it and removes it from PM2’s list.
What is fork mode?
Fork mode runs one independently managed application process.
What is cluster mode?
Cluster mode runs multiple Node.js application processes and distributes supported incoming connections among them.
Why must a clustered application be stateless?
Every process has separate memory. Data stored in one process is not automatically available in another process.
What is the difference between restart and reload?
Restart kills and starts the process again.
Reload replaces cluster workers more gradually and can provide zero-downtime application updates.
What does pm2 save do?
It saves the current PM2 process list.
What does pm2 startup do?
It configures the operating system to start PM2 during machine startup.
Where are PM2 logs stored?
They are stored under:
$HOME/.pm2/logs
Does PM2 fix application bugs?
No. It may restart a crashed process, but the developer must fix the underlying error.
Is PM2 required inside Docker?
Usually not. Docker can manage the container lifecycle, restart policy, logs and resource usage.
How should PM2 be used inside Docker when required?
Use:
pm2-runtime
instead of the normal PM2 daemon command.
What command is useful in CI/CD deployments?
pm2 startOrReload ecosystem.config.js --env production