Deciding Between PM2 Cluster Mode and Fork Mode for Node.js Applications
Learn how to choose between PM2 Fork Mode and Cluster Mode for Node.js apps, see trade‑offs, and validate your scaling setup with ecosystem.config.js and pm2 commands.
28 Feb 2026, 15:10 UTC

Decision: Choosing PM2 Execution Mode
When deploying a Node.js service you must decide whether to run it as a single process (Fork Mode) or to enable clustering across CPU cores (Cluster Mode). The decision depends on expected traffic, whether the application holds state in memory, and the memory limits of your host or container.
Comparison of Fork Mode and Cluster Mode
| Feature | Fork Mode | Cluster Mode |
|---|---|---|
| Primary Use Case | Small apps, CLI tools, background workers | Web servers, APIs, high‑traffic services |
| Scaling | Single instance | Horizontal across CPU cores |
| Zero‑Downtime Reload | No (full restart required) | Yes (via pm2 reload) |
| Load Balancing | None | Internal round‑robin |
| Memory Isolation | Isolated per process | Isolated per worker |
| Statefulness Requirement | Can store state in process memory | Must be stateless or use external store (Redis, DB) |
Trade‑offs
Fork Mode is simple and safe for memory‑heavy or stateful workers because only one instance runs, avoiding OOM from duplicate memory footprints. However, it cannot use more than one CPU core and does not provide zero‑downtime reloads.
Cluster Mode spreads connections over multiple workers, giving better throughput and allowing zero‑downtime updates. The trade‑off is that each worker duplicates the application’s memory, so total RAM usage grows linearly with the instance count. Additionally, any in‑memory session or cache must be externalized; otherwise users may lose data when a request jumps to a different worker.
Implementing with ecosystem.config.js
Define both a clustered API and a forked worker in the same configuration file.
module.exports = {
apps: [
{
name: 'my-api',
script: './src/index.js',
mode: 'cluster',
instances: 'max',
env: {
NODE_ENV: 'development'
},
prod: {
NODE_ENV: 'production'
}
},
{
name: 'worker-task',
script: './src/worker.js',
mode: 'fork',
instances: 1,
env: {
NODE_ENV: 'production'
}
}
]
};
To start the stack run:
pm2 start ecosystem.config.js
PM2 will launch my-api with as many workers as CPU cores and a single worker-task process.
Validating the Setup
- Check that the correct number of instances is running:
pm2 listYou should see multiple entries for
my-apieach with a different PID, and one entry forworker-task. - Verify load distribution under traffic:
pm2 monitWatch the CPU column; usage should be spread across the workers of
my-api. - Test zero‑downtime reload:
pm2 reload my-apiWhile the reload proceeds,
pm2 listwill show workers being stopped and started one at a time. Keep a simple HTTP request looping (e.g.,while true; do curl -s http://localhost:3000/health; sleep 0.1; done) and confirm you receive responses throughout. - Confirm memory growth:
pm2 show my-apiLook at the
Memoryfield; it should approximatebase memory × number of workers. If the value approaches your container’s limit, reduceinstancesor enable external storage for session data.
Limitations and Practical Checks
- Statefulness: If your app stores sessions in memory, replace with Redis or a database before using Cluster Mode.
- Memory limits: Monitor with
pm2 monitor container metrics; OOM kills will appear in logs asOut of memory. - Worker affinity: PM2’s internal round‑robin does not guarantee sticky connections; design accordingly.
After any change to instances or mode, run pm2 reload ecosystem.config.js and repeat the validation steps above.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.