Nodefony
Framework Node.js fullstack — HTTP & WebSocket, même contexte

Performance de Nodefony

Les chiffres sont mesurés à la main, sur une machine nommée, puis versionnés dans le dépôt — cette page ne fait que les rendre.

Où aller

Les mesures
comparatif, courbes de tenue dans la durée, décomposition de la mémoire, dimensionnement d'un pod, calculateur
Le chantier
le profilage, le lot annulé par son propre A/B, et les instruments qui ont menti
La méthode
le protocole, le décor, et les instruments qui ont menti avant qu'on s'en aperçoive
Le budget d'une requête
le pipeline, les autres frameworks, et les bases de données

Ce que Nodefony encaisse

Une route qui ne fait AUCUN travail applicatif, servie par le pipeline complet — sécurité, routage, contexte asynchrone, en-têtes : le pire cas pour un framework, puisqu'il y pèse 100 % du budget. Médiane de 3 tirs de 10 s à 64 connexions.

Débit
21 686 req/s
dispersion 0,7 %
Latence médiane
2,88 ms
la moitié des requêtes sous ce seuil
Latence p99
4,37 ms
99 requêtes sur 100 sous ce seuil
Face à Express équipé
113 %
du débit d'un Express qui fait le MÊME travail
Face à NestJS équipé
94 %
du débit d'un NestJS qui fait le MÊME travail
Tenue dans le temps
aucune fuite
88 min sous charge — empreinte à 1,67 Mo/h, tas JS à 0,14 Mo/h

Face à quoi

Débit mesuré, du serveur nu au pipeline complet
req/s Serveur nu (node:http) Express nu Express équipé (même travail) Nodefony (pipeline complet) 0 10 000 20 000 30 000 40 000 50 000 43 217 20 088 19 235 21 686 Débit par camp
req/s Serveur nu (node:http) Express nu Express équipé (même travail) Nodefony (pipeline complet) 0 10 000 20 000 30 000 40 000 50 000 43 217 20 088 19 235 21 686 Débit par camp

médiane de 3 tirs, même route, même machine, même fenêtre

Comparer un pipeline complet à un serveur nu ne compare pas le même travail. Le camp qui compte est Express équipé : même route, mêmes garanties — un scope AsyncLocalStorage avec identifiant de requête, la corrélation W3C traceparent, CORS, les en-têtes de sécurité, le contrôle anti-CSRF par Fetch Metadata, et le matching des zones du pare-feu, sur CHAQUE requête.

Ce que ces chiffres veulent dire

Un pipeline ne se juge pas au débit d'une route vide, mais à ce qu'il FAIT pendant qu'il la sert — et à ce qui reste de cet écart quand l'application, elle, commence à travailler.

Le prix des garanties est mesuré, et il est payé par tout le monde

Express nu rend 20 088 req/s ; le même Express, équipé des six briques ci-dessus, en rend 19 235. Équiper Express coûte 4,2 % de son débit. Ce prix n'est pas celui d'un framework : c'est celui des fonctionnalités, et il se paie quel que soit l'outil qui les rend. Nodefony arrive avec ces briques déjà en place — les 21 686 req/s ci-dessus sont mesurées pipeline complet traversé, pas moteur nu.

Reste alors l'écart d'implémentation, et lui seul : -5,9 µs par requête (46,1 µs contre 52,0 µs de temps de service). C'est le seul terrain où le choix du framework décide.

Puis le travail du développeur commence

Une application ne sert pas des routes vides : elle interroge une base, appelle un service, rend une vue. Ce travail-là s'ajoute au temps de service des deux côtés, tandis que l'écart de pipeline, lui, ne bouge pas. Sa part relative fond donc à mesure que l'application devient réelle. Le calculateur ci-dessous le montre sur VOS hypothèses.

Ce bloc est un CALCUL, pas une mesure. Il ajoute un temps de travail au temps de service des deux camps et en refait le rapport. Posez le curseur à 0 ms : il retombe sur les 112,7 % mesurés plus haut — c'est le seul contrôle qui vaille pour un modèle, retrouver la mesure là où elle existe. Le modèle est conservateur pour tout travail d'entrée-sortie : pendant qu'une requête attend sa base, elle ne consomme pas de processeur, et le débit réel baisse donc MOINS que ce que ce calcul annonce. Il vaut tel quel pour un travail qui consomme du processeur (sérialisation, rendu, chiffrement).

Ce que ce comparatif ne mesure pas

Le camp équipé reproduit six briques. Il ne reproduit ni les sessions, ni l'autorisation par rôles, ni le WebSocket co-citoyen du même contexte, ni l'ORM, ni le plan d'administration — tout ce qu'une application finit par réclamer. Chacune de ces briques, ajoutée à Express, sera un intergiciel de plus dans la chaîne, et se paiera comme les six premières se sont payées (4,2 %). Chez Nodefony, elles partagent la traversée déjà comptée dans les 21 686 req/s ci-dessus.

C'est une différence de STRUCTURE, et nous ne la chiffrons pas ici : il faudrait un banc par brique ajoutée, des deux côtés. Ce qui est chiffré, et qui suffit à situer le débat, c'est que le prix des six premières est déjà connu — et qu'il est plus élevé que l'écart de -5,9 µs qui sépare les deux pipelines complets.

Sur quoi ces chiffres ont été pris

Ce sont des mesures de développement, pas une promesse de production. Intel Core i9-8950HK @ 2.90 GHz, 12 cœurs logiques, 32 Go, macOS (darwin 24.6.0) — un portable, avec le générateur de charge sur la même machine. Les valeurs ABSOLUES sont donc basses pour tous les participants : seuls les rapports entre camps, pris dans la même fenêtre, sont exploitables.

Une page par version publiée

Ce qui a été mesuré, sur quelle machine, avec quel protocole — et ce que ces chiffres ne permettent PAS de conclure.

Nodefony 10.0.0 version courante2026-10-01

Le dossier du chantier

Où part le temps, et comment on l'a su — le profilage, les lots gardés, celui qui a été annulé par son propre A/B, les instruments qui ont menti avant qu'on s'en aperçoive, et ce qu'un chemin virtualisé interdit de conclure.

Ce dossier raconte le chantier jusqu'au 2026-08-07 ; chaque chiffre y porte l'état du code auquel il correspond. La suite — un GET sans promesse, les contrôleurs en instance unique, le budget d'une requête face à NestJS, le chemin ORM — est dans Où part le temps. Les mesures d'une version publiée, elles, sont dans le tableau ci-dessus.