eduardweb.
DevOps & VPSIntermediar#nodejs#devops#pm2#monitoring#express

Healthcheck care chiar funcționează pentru PM2: ce vede și ce ignoră

De Bogdan Răducanu, 22 iul. 2026 · 11 vizualizări · 3 like-uri

Postat 22 iul. 2026
typescript
import { Request, Response } from 'express';
import { pool } from './db';

let lastDbCheck = 0;
let isDbHealthy = true;

export async function readinessCheck(req: Request, res: Response) {
  const now = Date.now();
  
  // Cache-uim verificarea de DB timp de 10 secunde ca sa nu sufocam pool-ul
  if (now - lastDbCheck > 10000) {
    lastDbCheck = now;
    try {
      await Promise.race([
        pool.query('SELECT 1'),
        new Promise((_, reject) => setTimeout(() => reject(new Error('DB Timeout')), 2000))
      ]);
      isDbHealthy = true;
    } catch (err) {
      isDbHealthy = false;
    }
  }

  const heapUsageMB = process.memoryUsage().heapUsed / 1024 / 1024;
  const isHealthy = isDbHealthy && heapUsageMB < 850; // Limita de 850MB

  if (!isHealthy) {
    return res.status(503).json({
      status: 'unhealthy',
      db: isDbHealthy,
      heapMB: Math.round(heapUsageMB)
    });
  }

  return res.status(200).json({ status: 'ok', heapMB: Math.round(heapUsageMB) });
}

Am pățit-o pe un proiect cu peste 12k request-uri pe minut: PM2 raporta liniștit status: online, dar utilizatorii primeau 502 Bad Gateway sau așteptau 30 de secunde după un răspuns. Dacă te bazezi doar pe procesul master din PM2 că-ți zice că nodul trăiește, te minți singur. În postarea asta îți arăt cum am structurat un healthcheck real, ce metrici chiar contează și cum previi dezastrele silențioase din producție.

Iluzia lui "status: online" din PM2

PM2 e excelent pentru process management pe un singur VPS sau în clustere mici. Problema e că PM2 se uită doar dacă procesul Node.js are un PID activ în sistemul de operare. Atât.

Dacă event loop-ul e blocat de un JSON.parse uriaș pe un payload de 100MB, procesul e tot "online" pentru PM2. Dacă pool-ul de conexiuni la PostgreSQL e epuizat și toate query-urile stau în queue la infinit, PM2 vede procesul ca fiind perfect sănătos. Ba mai mult, dacă ai memorie scursă (memory leak) și ești la 99% heap limit, Node va procesa Garbage Collection ca nebunul, crescând latența la 5-10 secunde, dar tot va apărea verde în pm2 status.

Unde crapă verificările superficiale

Păcatul clasic pe care îl văd la mulți e endpoint-ul de /health care returnează pur și simplu { status: "ok" } direct din memorie.

Am făcut și eu greșeala asta acum vreo 6 ani. Dacă app-ul răspunde cu 200 OK la un ping chior, știi doar că Express sau Fastify poate ruta HTTP. Nu știi dacă poți scrie în Redis, nu știi dacă DB-ul răspunde în sub 100ms și nu știi cât de încărcat e event loop-ul.

A doua extremă e la fel de periculoasă: să faci SELECT 1 din DB la fiecare 2 secunde pe /health. Când ai 10 instanțe de PM2 și un load balancer care le verifică la fiecare secundă, generezi sute de query-uri inutile doar ca să întrebi "ești bine?". Am văzut cazuri în care healthcheck-ul a sufocat baza de date în timpul unui spike de trafic.

Cum am configurat o soluție care funcționează

Trag linia așa: un healthcheck bun e împărțit în două niveluri, Liveness și Readiness.

  1. Liveness Check (/live): Răspunde instant (sub 5ms) fără nicio interogare externă. Verifică doar starea internă Node.js: heap memory-ul curent și dacă event loop-ul nu e complet blocat. Dacă RSS-ul depășește pragul critic, pică liveness-ul și procesul e omorât.
  2. Readiness Check (/ready): Verifică dependențele (Postgres, Redis), dar cu cache pe rezultat (de exemplu, rezultatul verificării de DB e salvat 10-15 secunde în memorie). În felul ăsta nu omori baza de date cu query-uri redundante.

Asta ne-a salvat când am avut un deadlock pe DB: /ready a returnat 503, Nginx a scos nodul din rotație în 2 secunde, iar clienții n-au simțit nicio întrerupere.

PM2 ecosystem și restart-ul automat

Pe lângă max_memory_restart: '1G' din ecosystem.config.js, folosesc un script extern de monitoring (sau Uptime Kuma / Nginx healthcheck) care apelează /ready. Dacă apelezi endpoint-ul corect și pui un timeout strict de 2 secunde pe request, prinzi 99% din probleme înainte să le vadă utilizatorii.

Trade-off-ul e că un healthcheck prea strict îți poate băga aplicația într-o buclă infinită de restart-uri ("flapping"). De asta pun mereu o pauză de minim 30 de secunde după un reload înainte să activez alertele critice.

Tu ce folosești pentru monitoring la Node.js pe PM2: te bazezi pe ping-uri simple de HTTP sau ai integrat verificări pe event loop și conexiuni?

Răspunsuri 0

Se încarcă răspunsurile…

Loghează-te pentru a răspunde

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