19 déc. 2025
Déployer une application découplée basée sur Strapi (CMS headless) et Next.js (framework Javascript frontend) sur un serveur avec des ressources limitées demande une configuration fine. Entre les métriques trompeuses de consommation mémoire et les particularités de chaque framework, il est facile de se perdre. Nos recommandations techniques dans cet article.
Les défis pour une architecture découplée NodeJs basée sur Strapi et NextJs
Voici les points-clés à appréhender pour offrir à votre stack un système optimisé.
Strapi gourmand en RAM : Base de données, uploads, cache applicatif
Next.js en cluster vs Strapi en fork : Deux approches différentes
Cache Linux : Le mystère des "98% de RAM utilisée"
max-old-space-size : Comment le calculer correctement
La configuration PM2 recommandée pour Next.js
Next.js est stateless et bénéficie grandement du cluster mode de PM2. Cela permet de distribuer la charge entre plusieurs instances et d'obtenir du load balancing automatique.
Les principes clés appliqués
✅ Cluster Mode : Utilise tous les CPU cores
✅ Multiple Instances : Load balancing automatique
✅ Zero-downtime : Reload progressif sans coupure
✅ Heap optimisé : 75-96% de max_memory_restart
Notre recommandation pour Next.js
Pour un serveur avec 2 CPU et 4 Go de RAM :
Pourquoi cette configuration ?
max-old-space-size = 768M : Calculé à 96% de 800M pour laisser ~4% à Node.js (code, stack, buffers). C'est un ratio agressif mais optimal pour Next.js qui a besoin de beaucoup de heap pour le rendering.
cron_restart à 4h : Nettoie les fuites mémoire potentielles pendant les heures creuses. Même si votre code est parfait, certaines bibliothèques tierces peuvent avoir des micro-fuites.
exp_backoff_restart_delay : Évite les boucles de crash infinies avec des délais progressifs (100ms, 200ms, 400ms, etc.).
La configuration PM2 recommandée pour Strapi
Strapi a des besoins très différents de Next.js. Il est stateful et ne supporte PAS le cluster mode.
Les spécificités du CMS Strapi
⚠️ Fork Mode obligatoire : Cluster incompatible (uploads, cache local)
⚠️ Plus de RAM : DB queries + médias + cache applicatif
⚠️ Démarrage lent : Timeouts plus élevés nécessaires
⚠️ Headers larges : Uploads nécessitent --max-http-header-size
Notre recommandation pour Strapi
Pourquoi Fork et pas Cluster ?
En cluster mode, Strapi rencontre des problèmes critiques :
❌ Uploads perdus : Fichiers sauvegardés sur instance 1, requête suivante arrive sur instance 2
❌ Cache désynchronisé : Chaque instance a son propre cache en mémoire
❌ Locks de base de données : Conflits de transactions
❌ WebSockets cassés : L'admin panel utilise WebSocket et ne fonctionne pas en cluster
En fork mode, ces problèmes n'existent pas :
✅ Uploads cohérents
✅ Cache unifié
✅ Pas de conflit DB
✅ Admin panel stable
Calcul de max-old-space-size
Le paramètre --max-old-space-size définit la taille maximale du heap V8 (mémoire JavaScript) en mégaoctets.
La formule
Pourquoi pas 100% ?
Node.js utilise de la mémoire en dehors du heap :
Tableau de référence
RAM instance | max-old-space-size | Calcul | Usage |
256M | 192 | 256 × 0.75 | Micro instance |
512M | 384 | 512 × 0.75 | Small |
800M | 768 | 800 × 0.96 | Next.js (recommandé) |
1G | 896 | 1024 × 0.90 | Strapi (recommandé) |
2G | 1536 | 2048 × 0.75 | Large instance |
Script de calcul
Utilisation :
Répartition RAM (VPS 4 Go)
Voici la répartition optimale pour un serveur avec 4 Go de RAM et 2 CPU :
Cette configuration laisse une marge de sécurité confortable tout en maximisant les performances.
Comprendre la vraie consommation mémoire
Le mystère des 98% de RAM
Vous lancez free -m et voyez :
Question : Si 3 Go sont utilisés, pourquoi Kubernetes/Docker affiche-t-il 98% de RAM utilisée ?
Réponse : Le cache Linux (buff / cache)
Les trois métriques essentielles
1. RSS (Resident Set Size) - La vraie mémoire utilisée
Mémoire physique réellement allouée aux processus (heap + stack + code). C'est la consommation réelle de vos applications.
Exemple pour Next.js : 317 MB
2. Cache Linux (buff/cache) - Mémoire "reclaimable"
Linux met en cache les fichiers lus pour accélérer les I/O futures. Ce cache est automatiquement libéré si une application a besoin de mémoire.
Exemple : 1.3 GB (node_modules + .next/ + fichiers statiques)
3. Working Set - Ce qui compte vraiment
RSS + cache actif uniquement. C'est la métrique utilisée par Kubernetes pour décider des OOM kills.
Exemple : ~1.2 GB
L'équation Kubernetes
Répartition détaillée d'un pod Next.js
Verdict : Pas de memory leak ! Les 98% incluent le cache Linux qui est libérable instantanément. Le working_set à ~46% montre que l'application consomme réellement 920 MB, laissant 1 GB de vraie marge avant un OOM kill.
Que contient le cache ?
Linux met en cache tous les fichiers fréquemment lus :
node_modules/ : ~1 GB (100% en cache)
.next/cache/ : ~388 MB (ISR cache)
.next/static/ : ~8 MB (JS/CSS bundles)
.next/server/ : ~1 GB / 2 GB (48% en cache)
Ce cache améliore considérablement les performances en évitant les lectures disque répétées.
Monitoring et scripts utiles
Commandes PM2 essentielles
Script de vérification santé
Installation :
Script de surveillance mémoire
Les métriques à surveiller
En production
✅ memory.working_set : La vraie consommation (pas memory.usage !)
✅ restart_time : Nombre de restarts (anomalie si > 10/jour)
✅ cpu % : Alerte si > 80% constant
✅ heap used vs heap limit : Détecte les memory leaks
Alertes recommandées
Rotation des logs
Sans rotation, les logs peuvent remplir le disque rapidement.
Installation pm2-logrotate
Logs centralisés
Dans vos fichiers ecosystem.config.js :
Checklist de déploiement
Configuration PM2
cwd correctement défini avec path.join(__dirname)
max_memory_restart adapté à votre RAM
--max-old-space-size = 75-90% de max_memory_restart
instances : 2+ pour Next.js, 1 pour Strapi
exec_mode : cluster pour Next.js, fork pour Strapi
cron_restart défini (4h pour Next.js, 5h pour Strapi)
Logs avec rotation activée
env_production défini
Monitoring
pm2-logrotate installé et configuré
Health check scripts configurés
Alertes sur memory.working_set (pas memory.usage)
pm2 save après chaque changement
pm2 startup pour auto-restart au boot
Post-déploiement
Tableau récapitulatif
Paramètre | Next.js | Strapi | Explication |
exec_mode | cluster | fork | Next.js = stateless, Strapi = stateful |
instances | 2 (= nb CPU) | 1 | Cluster pour Next.js uniquement |
max_memory_restart | 800M | 1G | Strapi plus gourmand (DB + uploads) |
--max-old-space-size | 768 | 896 | 75-90% de max_memory_restart |
listen_timeout | 3000 | 10000 | Strapi démarre lentement |
cron_restart | 4h | 5h | Éviter restart simultané |
Formules clés
Calcul max-old-space-size
Exemple : 800M × 0.75 = 600M (ou × 0.96 pour être plus agressif = 768M)
Répartition RAM idéale (4 Go)
Vraie consommation mémoire
Surveillez working_set, pas usage !
Conclusion
L'optimisation d'une stack Strapi/Next.js en production nécessite une compréhension fine de :
La gestion mémoire Linux (buff/cache vs RAM réelle)
Les spécificités de PM2 (cluster vs fork, calcul heap)
Les limites de chaque framework (Next.js cluster-friendly, Strapi non)
Le monitoring proactif (working_set vs usage)
Les métriques peuvent être trompeuses : 98% de RAM utilisée ne signifie pas nécessairement un problème si la majorité est du cache Linux libérable.
L'optimisation est un processus itératif :
Déployer avec des valeurs conservatives
Monitorer pendant 1-2 semaines
Ajuster selon les données réelles
Documenter chaque changement
Avec les configurations et scripts fournis dans cet article, votre stack est maintenant production-ready et optimisée pour la performance et la stabilité.
Configuration testée avec Next.js 15, Strapi 4, PM2 5.x et Node.js 20+ sur serveur 4 Go RAM / 2 CPU
Share
Auteur



