eduardweb.
PM2 & NodeIntermediar#nodejs#devops#pm2#backend#javascript

Cum am configurat PM2 în producție: cluster mode, graceful reload și OOM restart

De Cosmin Rotaru, 11 aug. 2026 · 3 vizualizări · 2 like-uri

Postat acum 5 zile
javascript
module.exports = {
  apps: [{
    name: 'api-service',
    script: './dist/server.js',
    instances: 'max',
    exec_mode: 'cluster',
    max_memory_restart: '1G',
    listen_timeout: 10000,
    kill_timeout: 5000,
    env_production: {
      NODE_ENV: 'production',
      PORT: 3000
    }
  }]
};

Toți începem la fel: aruncăm un pm2 start app.js pe server, vedem verde în terminal și plecăm liniștiți. Problema apare la primul deploy în mijlocul zilei când pică conexiunile utilizatorilor sau la 3 dimineața când un memory leak umple tot RAM-ul. Hai să-ți arăt cum am structurat un ecosystem.config.js pe care-l folosesc de ani buni pe un API Node.js cu peste 12k cereri pe minut.

De la fork la cluster mode și zero downtime

Implicit, PM2 pornește aplicația în modul fork, adică un singur proces Node.js pe un singur nucleu CPU. Dacă ai un server cu 4 vCPU-uri, irosești 75% din resursă. Trecerea la exec_mode: 'cluster' și instances: 'max' schimbă totul: PM2 folosește modulul nativ cluster din Node și împarte traficul automat între procese.

Dar cluster mode-ul singur nu-ți garantează zero downtime la deploy. Când dai pm2 reload all, PM2 omoară procesele vechi și le pornește pe cele noi. Dacă aplicația ta durează 3 secunde să se conecteze la Postgres și Redis, în alea 3 secunde request-urile primite vor primi eroare 502.

Aici intervin listen_timeout, kill_timeout și handler-ul de SIGINT. În codul aplicației trebuie să prinzi semnalul de oprire, să oprești primirea de request-uri noi și să le prinzi pe cele în derulare înainte să închizi conexiunile la bază.

Auto-restart la OOM: centura de siguranță la memory leaks

Toți scriem cod imperfect. Anul trecut am avut un leak stupid într-o bibliotecă de generare de PDF-uri care mânca câte 50MB la fiecare export. Până să găsim bug-ul și să dăm fix, opțiunea max_memory_restart: '1G' ne-a salvat producția.

Când un worker sare de pragul setat (de exemplu 1GB), PM2 îl repornește în fundal, pe rând, fără să afecteze ceilalți workeri din cluster. Utilizatorul nici nu simte. Evident, nu e o soluție definitivă pentru memory leaks, dar e diferența dintre o notificare pe Slack și un incident grav la 4 dimineața.

Log rotation: cum să nu umpli SSD-ul

Implicit, PM2 scrie stdout și stderr în fișiere care cresc la nesfârșit. Am văzut un server picat pur și simplu pentru că fișierul out.log ajunsese la 45GB și umpluse tot disk-ul.

Soluția e să folosești modulul pm2-logrotate. Îl instalezi o singură dată global pe server cu pm2 install pm2-logrotate și îți va roti automat logurile când ating o anumită dimensiune (ex: 10M), păstrând doar ultimele N fișiere arhive.

Trade-off-uri reale pe care trebuie să le știi

Cluster mode e excelent, dar vine cu niște capcane evidente:

  1. Starea în memorie e interzisă: Dacă stochezi sesiuni, rate-limiting sau cache în variabile globale din Node, acestea nu vor fi distribuite între workeri. Ai nevoie neapărat de Redis.
  2. WebSocket-uri: Fără sticky sessions configurate în Nginx sau un adapter de Redis pentru Socket.io, handshake-ul va eșua când clientul nimerește alt worker.
  3. Consum mai mare de memorie RAM: Fiecare proces Node.js își cară propriul V8 runtime (cam 40-60MB doar la pornire).

Voi mai folosiți PM2 pe servere clasice sau ați mutat totul în Docker și Kubernetes?

Răspunsuri 0

Se încarcă răspunsurile…

Loghează-te pentru a răspunde

Doar membrii comunității pot lăsa comentarii.