Gérer, monitorer et déployer des applications Node.js en production avec PM2 — process manager, clusters, logs, déploiement automatisé et survie aux redémarrages.
Node.js est mono-thread. Un processus Node utilise au maximum un cœur CPU, même sur un serveur avec 8 ou 16 cœurs. Sans clustering, vous laissez 87% de votre CPU inutilisé.
Le module cluster natif de Node.js existe pour ça, mais l'implémenter correctement à la main demande du code boilerplate. PM2 le fait automatiquement, sans modifier votre application.
// Fork : 1 processus, 1 cœur
exec_mode: 'fork',
instances: 1
// Cluster : N processus, N cœurs
exec_mode: 'cluster',
instances: 4 // 4 cœurs
instances: 'max' // tous les cœurs disponiblesEn mode cluster, PM2 démarre un processus maître qui répartit les connexions entrantes entre N processus workers. Votre code ne change pas — chaque worker reçoit les requêtes HTTP comme s'il était le seul à tourner.
┌── worker 0 (port 3000)
Client ──► PM2 maître ──► worker 1 (port 3000)
└── worker 2 (port 3000)
└── worker 3 (port 3000)Les quatre workers écoutent sur le même port. PM2 gère le partage de socket en interne.
# Ligne de commande
pm2 start app.js -i max
# Via ecosystem.config.jsmodule.exports = {
apps: [{
name: 'api',
script: './index.js',
instances: 'max',
exec_mode: 'cluster',
}]
}pm2 start ecosystem.config.jsSur un VPS avec 2 vCPU, PM2 lance 2 instances. Sur 4 vCPU, 4 instances.
C'est l'avantage principal du mode cluster en production. pm2 reload redémarre les workers un par un — pendant qu'un worker redémarre, les autres continuent à servir les requêtes.
pm2 reload apiSéquence de reload :
1. PM2 envoie SIGINT à worker 0
2. Worker 0 finit ses requêtes en cours (graceful shutdown)
3. Worker 0 s'arrête
4. PM2 démarre un nouveau worker 0
5. Nouveau worker 0 est online
6. Répéter pour worker 1, 2, 3...Pendant toute la séquence, workers 1, 2, 3 continuent de répondre. Zéro downtime.
Pour que le zero-downtime fonctionne vraiment, votre application doit gérer proprement le signal SIGINT — finir les requêtes en cours avant de s'arrêter.
// Dans votre app Node.js
const server = app.listen(3000)
process.on('SIGINT', () => {
server.close(() => {
// Fermer les connexions DB, etc.
process.exit(0)
})
// Timeout de sécurité si le shutdown prend trop de temps
setTimeout(() => process.exit(1), 10000)
})Sans ça, PM2 envoie SIGINT, Node ignore ou crashe, et PM2 tue le processus de force après le kill_timeout.
{
kill_timeout: 5000, // attendre 5s avant SIGKILL forcé
listen_timeout: 8000, // attendre 8s que le worker soit "ready"
wait_ready: true, // attendre signal process.send('ready')
}Avec wait_ready: true, PM2 attend que votre app envoie process.send('ready') avant de considérer le worker comme opérationnel :
app.listen(3000, () => {
if (process.send) process.send('ready')
})Un point critique : en mode cluster, chaque worker est un processus Node.js séparé. Il n'y a pas de mémoire partagée entre les workers.
// ❌ Ça ne marche pas en cluster
const sessions = {} // chaque worker a son propre objet sessions
// ✅ Utiliser un store partagé
import Redis from 'ioredis'
const sessionStore = new Redis() // Redis est externe, partagé par tousSessions en mémoire, caches locaux, WebSockets avec état — tout ce qui suppose un seul processus pose problème en mode cluster. La solution classique : externaliser dans Redis.
pm2 list┌────┬──────┬──────────┬──────────┬─────────┬──────────┬────────┬──────┐
│ id │ name │ mode │ pid │ status │ cpu │ mem │ ↺ │
├────┼──────┼──────────┼──────────┼─────────┼──────────┼────────┼──────┤
│ 0 │ api │ cluster │ 12340 │ online │ 0% │ 68 MB │ 0 │
│ 1 │ api │ cluster │ 12341 │ online │ 0% │ 71 MB │ 0 │
│ 2 │ api │ cluster │ 12342 │ online │ 0% │ 69 MB │ 0 │
│ 3 │ api │ cluster │ 12343 │ online │ 0% │ 70 MB │ 0 │
└────┴──────┴──────────┴──────────┴─────────┴──────────┴────────┴──────┘Chaque worker a son propre ID, PID, et compteur de restarts. Si un seul worker crashe en boucle (↺ élevé), le problème vient d'une requête spécifique ou d'un état corrompu — pas de l'app entière.
# Ajouter des workers sans arrêter
pm2 scale api +2
# Passer à un nombre précis
pm2 scale api 6
# Réduire
pm2 scale api 2Utile pendant des pics de charge — ajouter des workers temporairement sans aucune coupure.
Le mode cluster extrait les performances de votre serveur sans toucher au code. Le chapitre suivant couvre les logs et le monitoring — indispensables pour savoir ce qui se passe en production.