module.exports = {
apps: [{
name: 'api-prod',
script: './dist/server.js',
instances: 'max',
exec_mode: 'cluster',
max_memory_restart: '700M',
kill_timeout: 5000,
listen_timeout: 8000,
env_production: {
NODE_ENV: 'production',
PORT: 3000
},
error_file: './logs/err.log',
out_file: './logs/out.log',
merge_logs: true,
log_date_format: 'YYYY-MM-DD HH:mm:ss Z'
}]
};Dacă încă lansezi aplicații Node.js în producție dând comenzi de tipul pm2 start app.js --name api, te complici inutil. M-am lovit de chestia asta acum vreo doi ani la un client cu un e-commerce ce ducea peste 12k useri zilnici: la fiecare deploy cădeau conexiunile active, iar o dată la trei săptămâni discul se umplea complet din cauza logurilor text scăpate sub control.
Soluția curată este un fișier ecosystem.config.js bine structurat. Îți oferă control total peste procese și poți face versiunare direct în Git.
Cluster Mode și Zero Downtime la Deploy
Setarea exec_mode: 'cluster' împreună cu instances: 'max' (sau un număr fix de nuclee) distribuie traficul pe toate nucleele procesorului folosind modulul nativ de cluster din Node.js. Performanța crește instant, dar capcana mare e la deploy.
Dacă dai pm2 restart, PM2 omoară toate procesele deodată și aplicația e picată 2-3 secunde. Răspunsul corect este pm2 reload ecosystem.config.js --env production. PM2 repornește instanțele una câte una.
Ca să funcționeze impecabil, trebuie să configurezi doi parametri critici:
kill_timeout: Îi spune procesului PM2 cât timp să aștepte după ce a trimisSIGINTpentru ca aplicația să-și închidă conexiunile la baza de date și request-urile HTTP active. Eu pun 5000ms.listen_timeout: Timpul maxim acordat noii instanțe să trimită semnalul că e gata să primească trafic.
Atenție la un trade-off major: dacă salvezi sesiuni utilizator direct în memoria aplicației sau folosești WebSocket-uri fără un adapter de Redis, cluster mode o să-ți rupă starea aplicației. Treci starea în Redis înainte să dai enable la cluster.
Limitarea memoriei: Band-aid-ul necesar pentru OOM
Oricât de atenți suntem la code review, leak-urile de memorie mai scapă. Am pățit-o la un serviciu care genera PDF-uri mari: procesul Node urca la 1.5GB RAM și bloca tot VPS-ul.
Cu opțiunea max_memory_restart: '700M', PM2 monitorizează constant consumul. Dacă procesul depășește pragul, e repornit automat în fundal, elegant, fără ca utilizatorii să vadă vreo eroare 502. Nu este o rezolvare definitivă a bug-ului de memorie, ci o plasă de siguranță până când identifici problema cu un profiler.
Rotirea logurilor și curățenia pe disc
Setările error_file și out_file trimit output-ul în fișiere dedicate, iar merge_logs: true combină logurile din toate instanțele din cluster într-un singur loc, altfel te trezești cu 8 fișiere separate.
Totuși, PM2 nu face log rotation nativ doar din configurarea asta. Trebuie să instalezi modulul lor separat o singură dată pe server: pm2 install pm2-logrotate. Fără el, un singur console.log pus într-un loop de websocket îți umple un disc de 40GB în trei zile.
Tu ce configurație folosești pentru PM2 în producție sau ai trecut deja complet pe Docker și Kubernetes?