Nodefony peut-il partir en production ?
Trois mesures — débit à travail égal, tenue dans la durée, dimensionnement d'un pod — et ce qu'elles ne prouvent pas.
Le verdict
La performance n'est pas le point faible de Nodefony. À travail égal — c'est-à-dire
face à un Express muni des mêmes middlewares (scope ALS, CORS, en-têtes de sécurité, contrôle CSRF,
corrélation traceparent, zones de pare-feu) — le framework rend
92 % du débit pour +2,40 ms
de p99. L'écart avec un serveur nu ne mesure pas une lenteur : il mesure le travail que le serveur nu
ne fait pas.
Sur 20 minutes de charge continue, le tas ne monte pas et le débit ne s'érode pas. Le risque résiduel d'un passage en production n'est donc pas la performance — il est nommé plus bas.
1 · Où se situe Nodefony
Même route, même charge utile, même protocole de mesure, même concurrence (c64),
NODE_ENV=production. Chaque valeur est la médiane de 3 tirs, une série
étant refusée au-delà de 3 % de dispersion.
| node:http nu | 33 821 | 1,82 | 2,93 | 2,5 % | aucun framework — plancher théorique |
| Fastify | 31 960 | 1,94 | 3,09 | 1,3 % | routing + sérialisation schématisée |
| Express (nu) | 17 418 | 3,54 | 5,69 | 1,7 % | route + res.json(), rien d'autre |
| Express équipé | 13 333 | 4,66 | 7,17 | 1,9 % | ALS, CORS, en-têtes de sécurité, CSRF, traceparent, zones |
| Nodefony | 12 226 | 4,97 | 9,57 | 0,5 % | le même travail, intégré au pipeline |
res.json() revient à comparer une berline équipée à un kart. L'écart
entre les deux lignes Express (17 418 →
13 333 req/s) chiffre le prix de ces fonctionnalités, indépendamment de Nodefony.2 · La tenue dans la durée
20 minutes de trafic continu, 18 fenêtres retenues sur 20 (les premières sont écartées : un tas monte jusqu'à son régime). Ce banc cherche une pente, pas un écart entre deux mesures bruitées.
3 · Dimensionner un pod
Constantes relevées par capacity.mjs en development (profiler ACTIF ⇒ borne basse) — le profileur et
le chronométrage y sont actifs, donc ces chiffres sont une borne basse : en
production ils montent.
Ce que ces chiffres ne disent PAS
Un rapport qui ne montre que ses bons résultats rassure au lieu d'aider à décider. Les limites de cette campagne, nommées :
- 20 minutes ne sont pas trois jours. Ce soak élimine les fuites grossières. Une fuite lente — quelques mégaoctets par heure — resterait invisible ici et tuerait un pod au bout d'une semaine.
- Aucune valeur ABSOLUE n'est transposable. Poste de développement, macOS, 12 cœurs logiques, base de données derrière Docker Desktop. Les comparaisons à l'intérieur de cette page sont valides (même décor des deux côtés) ; les chiffres bruts, non.
- Le multi-pod sous trafic réel n'est pas couvert ici — fan-out entre pods, backplane Redis, cohérence des sessions. D'autres bancs le font, pas celui-ci.
- Le démarrage à froid coûte. Un pipeline riche présente plus de fonctions distinctes à optimiser au JIT : les premiers milliers de requêtes d'un pod neuf sont plus lentes. À couvrir par une sonde de disponibilité qui attend, ou un préchauffage.
- Aucune mesure ne remplace des heures de vol. C'est le déficit réel, et il ne se comble pas en codant : il se comble en étant déployé.
Décor et provenance
| Élément | Valeur |
|---|---|
| Node.js | v26.7.0 |
| Cœurs logiques | 12 |
| Processeur | Intel Core i9-8950HK @ 2.90 GHz |
| Concurrence (wrk) | c64 · 4 fils · 10s par tir |
| Route du comparatif | http://127.0.0.1:5151/nodefony/test/als-test/state |
| Route du soak | http://127.0.0.1:5151/nodefony/test/als-test/state |
| Tirs par mesure | 3, médiane retenue, refus au-delà de 3 % de dispersion |
| Fenêtres du soak | 20 × 60s, 2 écartée(s) |
# comparatif (une ligne par pile)
BENCH_CONN=64 bash .claude/skills/nodefony-load-test/bench-frameworks/bench.sh <bare|fastify|express|express-fair> 5161
BENCH_CONN=64 BENCH_URL=http://127.0.0.1:5151/nodefony/test/als-test/state \
bash .claude/skills/nodefony-load-test/scripts/bench-ab-mono.sh nodefony NF_WITH_DEV_MODULES=1
# tenue dans la durée
node .claude/skills/nodefony-load-test/scripts/soak.mjs --minutes 20 --window 60
# capacité
node .claude/skills/nodefony-load-test/scripts/capacity.mjs
# cette page
node .claude/skills/nodefony-load-test/scripts/prod-readiness-report.mjs