PM2 cluster mode dla Node.js — konfiguracja produkcyjna
Opublikowano: 9 kwietnia 2026 · Kategoria: DevOps
Node.js jest single-threaded — jeden proces obsługuje requesty na jednym rdzeniu CPU, a
reszta rdzeni stoi bezczynnie. Na serwerze z 8 vCPU marnujesz 87% procesora, jeśli
uruchomisz aplikację przez zwykłe node server.js. Rozwiązaniem jest PM2 cluster
mode — menedżer procesów, który uruchamia N kopii twojej aplikacji i równoważy ruch między
nimi. Bez zmiany kodu aplikacji, z zero-downtime reloadem i automatycznym restartem przy
crashu.
Instalacja i podstawowe komendy
PM2 instalujemy globalnie przez npm lub pnpm. Na produkcji warto też skonfigurować PM2 jako serwis systemd, żeby aplikacja automatycznie wstawała po restarcie serwera.
# Instalacja globalna
npm install -g pm2
# Start aplikacji w cluster mode (4 workery)
pm2 start app.js -i 4
# Start z max workers (tyle ile CPU)
pm2 start app.js -i max
# Start przez ecosystem file
pm2 start ecosystem.config.js --env production
# Status wszystkich aplikacji
pm2 status
# Logi w czasie rzeczywistym
pm2 logs
# Zero-downtime reload (po deploymencie)
pm2 reload all
# Restart (hard, z przerwa)
pm2 restart all
# Zapisz biezaca liste procesow
pm2 save
# Skonfiguruj autostart po reboot serwera
pm2 startup systemd Fork mode vs Cluster mode
PM2 obsługuje dwa tryby uruchamiania: fork (domyślny) i cluster. Różnica jest fundamentalna — fork to jeden proces, cluster to N procesów synchronizowanych przez Node.js cluster API.
| Cecha | Fork mode | Cluster mode |
|---|---|---|
| Liczba procesów | 1 | N (workers) |
| Load balancing | Brak | Round-robin (OS) |
| Wykorzystanie CPU | 1 rdzeń | Wszystkie rdzenie |
| Zero-downtime reload | Nie | Tak |
| Współdzielony stan | Jest (w pamięci) | Brak (Redis/DB) |
| Kompatybilność | 100% | Aplikacja musi być stateless |
Cluster mode wymaga, żeby aplikacja była stateless — każdy request może trafić do dowolnego
workera, więc sesje trzymaj w Redis/DB, nie w globalThis ani w module-level zmiennych.
WebSockety wymagają dodatkowo sticky sessions na poziomie reverse proxy (Nginx ip_hash).
Pełny ecosystem.config.js
ecosystem.config.js to deklaratywna konfiguracja PM2 — wszystko w jednym pliku, łatwa
do wersjonowania w git. Definiujesz apps (lista aplikacji), env-y (zmienne środowiskowe per stage),
strategię restartu, limity pamięci i logi.
module.exports = {
apps: [
{
name: 'api',
script: './dist/server.js',
instances: 'max', // tyle ile CPU
exec_mode: 'cluster', // cluster mode
max_memory_restart: '500M', // restart gdy RAM > 500MB
autorestart: true,
watch: false, // NIE watchuj na produkcji
max_restarts: 10,
min_uptime: '10s',
restart_delay: 4000,
env: {
NODE_ENV: 'development',
PORT: 3000,
},
env_production: {
NODE_ENV: 'production',
PORT: 3000,
LOG_LEVEL: 'info',
},
// Logi
error_file: '/var/log/pm2/api-error.log',
out_file: '/var/log/pm2/api-out.log',
log_date_format: 'YYYY-MM-DD HH:mm:ss',
merge_logs: true,
// Graceful shutdown
kill_timeout: 5000,
wait_ready: true,
listen_timeout: 10000,
},
{
name: 'worker',
script: './dist/worker.js',
instances: 2,
exec_mode: 'fork', // worker w fork mode
autorestart: true,
cron_restart: '0 4 * * *', // restart codziennie o 4:00
},
],
}; Logrotate i monitoring
Logi PM2 rosną szybko i bez rotacji zjedzą dysk. Moduł pm2-logrotate obraca pliki
logów według rozmiaru i czasu, z kompresją gzip. Instaluje się go jako moduł PM2, a konfigurujesz
przez pm2 set.
# Instalacja modulu logrotate
pm2 install pm2-logrotate
# Konfiguracja rotacji
pm2 set pm2-logrotate:max_size 50M # rotacja gdy plik > 50MB
pm2 set pm2-logrotate:retain 14 # trzymaj 14 plikow historycznych
pm2 set pm2-logrotate:compress true # kompresuj rotowane logi
pm2 set pm2-logrotate:rotateInterval '0 0 * * *' # co noc o polnocy
# Wyswietl aktualna konfiguracje
pm2 conf
# Monit — dashboard w terminalu
pm2 monit
# Szczegolowe info o procesie
pm2 describe api
# Metryki live (CPU, RAM per worker)
pm2 list pm2 monit to wbudowany dashboard w terminalu — pokazuje CPU, RAM i logi każdego workera
w czasie rzeczywistym. Dla produkcji warto go połączyć z zewnętrznym monitoringiem przez
pm2-prometheus lub wysyłać metryki do Grafana przez custom agent.
Zero-downtime reload
Największą zaletą cluster mode jest możliwość wdrożenia nowej wersji kodu bez przerwy w
działaniu. pm2 reload po kolei kills każdego workera, startuje nowego z nowym kodem,
czeka aż wejdzie w stan ready i dopiero potem przechodzi do kolejnego. Dla użytkownika
nie ma żadnego 502.
Żeby reload działał idealnie, aplikacja musi obsługiwać graceful shutdown — po otrzymaniu
sygnału SIGINT/SIGTERM przestaje przyjmować nowe requesty, kończy aktywne
i dopiero wtedy kończy proces. W ecosystem file ustaw kill_timeout (domyślnie 1600ms
— często za mało, podnieś do 5000-10000 ms).
Dodatkowo ustaw wait_ready: true i w kodzie aplikacji wyślij process.send('ready') dopiero po pełnej inicjalizacji (DB connection, cache warmup). PM2 wtedy czeka na ten sygnał
zanim przekaże ruch do nowego workera — i masz gwarancję, że użytkownicy nigdy nie dostaną odpowiedzi
z half-initialized instancji.