# Benchmarks

El mismo trabajo y el mismo tráfico. Explora las mediciones, conoce el método y reproduce cada prueba.

## Qué se ha medido

Ocho adaptadores, cuatro cargas y objetivos comunes de 100 y 1.000 peticiones/s: 192 mediciones. Cada medición inicia un proceso nuevo en producción: comprobación de respuesta, 1,5 s iniciales, 15 s de calentamiento, 6 s de reposo, 60 s de carga y 30 s de recuperación. Se conservan las tres repeticiones. Los adaptadores se ejecutaron uno a uno. Se comprueba el cuerpo completo de las respuestas antes y después de la carga; el generador solicita hasta 32 conexiones.

Total5 utiliza NEWSCHEMA compacto y controlador directo para validar JSON; el JSON sencillo se devuelve desde el controlador. Se incluyen escenarios completos registrados, sin escoger el mejor resultado numérico. Meteor usa su bundle de producción solo de servidor; NestJS usa su adaptador Express. Los validadores nativos cubren el cuerpo medido; las conversiones y el rechazo de entradas pueden diferir entre frameworks.

## Entorno

Servidor Linux x64 compartido, Intel Core i7-6700. Cada contenedor de medición tenía un límite de 2 CPU lógicas y 2 GiB, sin red exterior ni puertos publicados. El generador y la dependencia simulada compartían contenedor. Total4, Express, Fastify y Node http utilizaron Node 24.14.1; Total5, Meteor, AdonisJS y NestJS, Node 24.15.0, la versión requerida por el bundle de Meteor. Los datos originales conservan el runtime de cada framework: las diferencias no pueden atribuirse solo al framework. Los servicios de producción del servidor siguieron funcionando.

## Qué no demuestran estos resultados

Es un experimento con límite de tráfico y cliente de bucle cerrado, no una clasificación de capacidad máxima. Alcanzar el objetivo no demuestra cómo se comportan los adaptadores con llegadas independientes o saturación. Hubo cierta limitación de CPU por cuota, registrada en la revisión. Tres repeticiones cortas no demuestran estabilidad a largo plazo, ausencia de fugas de memoria, seguridad en producción, comportamiento de Flow ni consumo en Raspberry Pi. No se forzó el recolector de basura. El RSS puede seguir reservado al cesar el tráfico.

Una medición se considera saludable si las completadas alcanzan el 95 % del objetivo por duración del generador, el p99 no supera 250 ms y no hay errores, timeouts ni respuestas no-2xx. Este umbral no afirma que todos tengan la misma capacidad máxima.

## Cómo interpretar el resultado

Compara la misma carga al mismo ritmo y consulta conjuntamente latencia, CPU, memoria, errores y cobertura del objetivo. También influye la versión del runtime. Estas mediciones no demuestran que un framework consuma siempre menos recursos. Total.js 4 y 5 aparecen por separado, cada uno con la implementación y el runtime registrados.

## Comparación completa de frameworks

Finalizada: 2026-10-18T13:56:39.143Z; Node v24.14.1 / v24.15.0 (see runtimeByFramework).

| Framework | Node | Workload | req/s | Healthy | RSS baseline MiB | RSS load MiB | RSS recovery MiB | CPU % | p99 ms |
|---|---|---|---:|---|---|---|---|---|---|
| Total.js 4 | v24.14.1 | hello | 100 | 3/3 | 61.2 [61.0–61.2] | 89.8 [87.0–90.7] | 91.0 [88.3–105.4] | 1.7 [1.7–1.7] | 5.0 [5.0–6.0] |
| Express | v24.14.1 | hello | 100 | 3/3 | 74.2 [74.1–74.3] | 90.7 [90.4–91.5] | 90.8 [90.3–91.5] | 1.9 [1.9–2.0] | 7.0 [6.0–7.0] |
| Fastify | v24.14.1 | hello | 100 | 3/3 | 76.0 [75.5–76.0] | 91.3 [91.0–91.9] | 91.4 [91.0–91.9] | 1.4 [1.4–1.4] | 5.0 [5.0–5.0] |
| Node.js http | v24.14.1 | hello | 100 | 3/3 | 50.2 [50.2–50.3] | 68.8 [66.6–69.2] | 69.2 [67.0–69.5] | 1.4 [1.4–1.4] | 5.0 [5.0–5.0] |
| Total.js 4 | v24.14.1 | catalog | 100 | 3/3 | 61.3 [61.1–62.1] | 104.6 [94.9–106.2] | 106.4 [105.1–108.6] | 2.1 [2.1–2.1] | 8.0 [8.0–8.0] |
| Express | v24.14.1 | catalog | 100 | 3/3 | 74.1 [74.0–74.1] | 92.0 [91.9–94.5] | 92.3 [91.9–94.5] | 2.3 [2.3–2.4] | 9.0 [9.0–9.0] |
| Fastify | v24.14.1 | catalog | 100 | 3/3 | 75.8 [75.2–75.8] | 93.2 [92.6–93.4] | 93.4 [93.1–93.5] | 1.9 [1.8–1.9] | 8.0 [7.0–8.0] |
| Node.js http | v24.14.1 | catalog | 100 | 3/3 | 50.2 [50.1–50.3] | 66.0 [65.9–68.4] | 66.3 [66.1–68.7] | 1.8 [1.8–1.8] | 6.0 [6.0–7.0] |
| Total.js 4 | v24.14.1 | validate | 100 | 3/3 | 61.4 [61.3–61.6] | 96.4 [95.4–100.2] | 100.8 [98.3–101.9] | 2.0 [2.0–2.2] | 7.0 [6.0–8.0] |
| Express | v24.14.1 | validate | 100 | 3/3 | 74.0 [74.0–75.0] | 98.5 [94.4–99.0] | 98.6 [94.4–99.3] | 2.3 [2.2–2.3] | 9.0 [8.0–9.0] |
| Fastify | v24.14.1 | validate | 100 | 3/3 | 75.7 [75.6–76.0] | 97.3 [96.6–98.0] | 97.7 [96.2–98.0] | 1.7 [1.6–1.7] | 6.0 [5.0–6.0] |
| Node.js http | v24.14.1 | validate | 100 | 3/3 | 50.3 [50.2–50.5] | 71.6 [71.4–72.2] | 71.8 [71.4–72.6] | 1.7 [1.7–1.7] | 6.0 [6.0–6.0] |
| Total.js 4 | v24.14.1 | upstream | 100 | 3/3 | 67.2 [66.8–67.9] | 167.8 [166.7–169.5] | 175.3 [169.6–176.7] | 5.7 [5.7–5.8] | 19.0 [19.0–19.0] |
| Express | v24.14.1 | upstream | 100 | 3/3 | 80.2 [79.8–80.2] | 171.3 [171.2–171.4] | 173.7 [172.9–173.7] | 6.0 [5.7–6.2] | 20.0 [19.0–20.0] |
| Fastify | v24.14.1 | upstream | 100 | 3/3 | 80.3 [80.1–80.7] | 165.9 [165.8–168.4] | 168.7 [168.3–173.1] | 5.6 [4.8–5.8] | 20.0 [19.0–20.0] |
| Node.js http | v24.14.1 | upstream | 100 | 3/3 | 60.8 [60.7–61.6] | 161.9 [158.4–172.1] | 164.2 [159.9–174.2] | 5.5 [5.2–5.5] | 18.0 [18.0–19.0] |
| Total.js 4 | v24.14.1 | hello | 1000 | 3/3 | 61.0 [60.9–61.1] | 159.3 [150.1–167.0] | 174.3 [172.9–174.5] | 7.9 [7.8–8.2] | 5.0 [5.0–5.0] |
| Express | v24.14.1 | hello | 1000 | 3/3 | 74.1 [73.9–74.2] | 90.8 [90.4–91.5] | 90.9 [90.5–91.6] | 7.3 [7.1–7.6] | 5.0 [4.0–5.0] |
| Fastify | v24.14.1 | hello | 1000 | 3/3 | 75.9 [75.4–76.8] | 91.2 [91.0–91.6] | 91.2 [91.0–91.6] | 4.9 [4.9–5.0] | 3.0 [3.0–3.0] |
| Node.js http | v24.14.1 | hello | 1000 | 3/3 | 50.2 [50.2–50.2] | 67.9 [67.5–69.8] | 67.9 [67.7–70.0] | 4.4 [4.4–4.5] | 3.0 [3.0–3.0] |
| Total.js 4 | v24.14.1 | catalog | 1000 | 3/3 | 61.2 [61.0–61.3] | 179.5 [179.5–180.0] | 179.9 [179.4–180.2] | 9.9 [9.9–9.9] | 13.0 [6.0–18.0] |
| Express | v24.14.1 | catalog | 1000 | 3/3 | 73.8 [73.7–74.0] | 91.8 [91.1–92.9] | 91.8 [91.3–92.9] | 9.5 [9.4–9.8] | 5.0 [5.0–11.0] |
| Fastify | v24.14.1 | catalog | 1000 | 3/3 | 75.7 [75.3–75.9] | 94.1 [93.8–94.2] | 94.1 [93.8–94.2] | 7.1 [7.1–7.1] | 5.0 [5.0–5.0] |
| Node.js http | v24.14.1 | catalog | 1000 | 3/3 | 50.2 [50.1–50.2] | 72.6 [71.2–72.9] | 72.6 [71.2–73.2] | 7.3 [7.2–7.4] | 5.0 [4.0–5.0] |
| Total.js 4 | v24.14.1 | validate | 1000 | 3/3 | 62.2 [61.6–62.5] | 171.9 [170.7–172.7] | 175.7 [175.3–176.6] | 9.7 [9.5–10.0] | 6.0 [6.0–6.0] |
| Express | v24.14.1 | validate | 1000 | 3/3 | 74.4 [74.2–74.6] | 98.8 [98.2–99.7] | 98.8 [98.2–99.7] | 8.9 [8.9–9.2] | 8.0 [6.0–21.0] |
| Fastify | v24.14.1 | validate | 1000 | 3/3 | 75.9 [75.7–76.4] | 98.1 [98.1–98.4] | 98.1 [98.1–98.5] | 6.3 [6.2–6.3] | 5.0 [4.0–12.0] |
| Node.js http | v24.14.1 | validate | 1000 | 3/3 | 50.2 [50.2–50.4] | 71.0 [70.4–72.6] | 74.9 [74.2–76.4] | 6.2 [6.0–6.3] | 4.0 [4.0–13.0] |
| Total.js 4 | v24.14.1 | upstream | 1000 | 3/3 | 67.8 [67.8–67.8] | 202.3 [201.4–204.1] | 203.0 [201.6–204.7] | 36.3 [34.7–36.6] | 16.0 [15.0–16.0] |
| Express | v24.14.1 | upstream | 1000 | 3/3 | 80.7 [79.7–80.9] | 178.7 [177.6–187.7] | 182.6 [181.9–190.4] | 35.0 [32.6–35.4] | 15.0 [15.0–16.0] |
| Fastify | v24.14.1 | upstream | 1000 | 3/3 | 79.3 [79.3–79.3] | 194.0 [179.4–194.6] | 194.0 [179.6–194.9] | 33.8 [27.7–34.2] | 15.0 [14.0–15.0] |
| Node.js http | v24.14.1 | upstream | 1000 | 3/3 | 60.9 [60.7–61.0] | 171.9 [171.8–174.6] | 178.0 [175.5–179.3] | 29.0 [23.6–30.5] | 14.0 [13.0–15.0] |
| Meteor | v24.15.0 | hello | 100 | 3/3 | 123.7 [123.5–124.7] | 130.2 [128.1–131.3] | 159.1 [151.6–160.9] | 3.5 [3.5–3.6] | 15.0 [14.0–19.0] |
| Meteor | v24.15.0 | catalog | 100 | 3/3 | 124.7 [123.3–124.8] | 138.9 [138.8–139.4] | 162.5 [157.0–162.7] | 3.9 [3.9–4.0] | 15.0 [14.0–16.0] |
| Meteor | v24.15.0 | validate | 100 | 3/3 | 124.4 [123.2–124.6] | 137.0 [134.6–138.8] | 163.4 [161.2–169.2] | 3.9 [3.8–3.9] | 18.0 [15.0–22.0] |
| Meteor | v24.15.0 | upstream | 100 | 3/3 | 126.5 [126.2–127.6] | 187.0 [181.6–188.3] | 188.9 [184.5–191.2] | 8.0 [7.7–8.1] | 25.0 [24.0–25.0] |
| Meteor | v24.15.0 | hello | 1000 | 3/3 | 124.3 [123.4–125.5] | 168.6 [167.6–171.1] | 169.0 [168.5–172.3] | 12.8 [12.7–12.8] | 10.0 [8.0–18.0] |
| Meteor | v24.15.0 | catalog | 1000 | 3/3 | 124.1 [123.3–124.2] | 167.6 [167.6–172.5] | 168.0 [167.7–173.2] | 15.2 [15.1–15.9] | 10.0 [9.0–10.0] |
| Meteor | v24.15.0 | validate | 1000 | 3/3 | 125.2 [124.6–126.1] | 174.9 [173.8–175.0] | 176.3 [175.0–176.6] | 14.8 [14.6–14.9] | 10.0 [9.0–13.0] |
| Meteor | v24.15.0 | upstream | 1000 | 3/3 | 127.8 [127.2–128.3] | 213.9 [213.8–217.2] | 124.5 [122.1–126.7] | 38.2 [36.8–41.4] | 18.0 [17.0–19.0] |
| AdonisJS | v24.15.0 | hello | 100 | 3/3 | 114.9 [113.9–115.3] | 143.4 [143.0–149.2] | 144.3 [143.1–149.4] | 2.5 [2.3–2.5] | 9.0 [9.0–10.0] |
| AdonisJS | v24.15.0 | catalog | 100 | 3/3 | 114.4 [113.7–116.0] | 142.7 [142.7–142.9] | 143.6 [142.9–144.3] | 3.0 [3.0–3.1] | 13.0 [12.0–13.0] |
| AdonisJS | v24.15.0 | validate | 100 | 3/3 | 114.5 [114.3–115.0] | 147.0 [146.6–147.4] | 148.5 [148.1–148.5] | 3.0 [2.9–3.0] | 12.0 [12.0–13.0] |
| AdonisJS | v24.15.0 | upstream | 100 | 3/3 | 115.9 [112.8–116.2] | 195.2 [194.7–198.7] | 197.2 [194.8–199.7] | 6.3 [6.1–6.3] | 20.0 [20.0–21.0] |
| AdonisJS | v24.15.0 | hello | 1000 | 3/3 | 114.3 [113.6–115.4] | 145.3 [144.6–149.7] | 145.3 [144.6–149.6] | 10.7 [10.4–10.7] | 6.0 [6.0–7.0] |
| AdonisJS | v24.15.0 | catalog | 1000 | 3/3 | 113.7 [113.2–114.4] | 149.3 [149.2–151.7] | 151.8 [151.7–153.0] | 14.5 [14.4–14.7] | 9.0 [8.0–9.0] |
| AdonisJS | v24.15.0 | validate | 1000 | 3/3 | 115.2 [115.1–115.7] | 149.4 [149.0–149.8] | 149.4 [148.9–149.5] | 13.7 [13.6–14.3] | 9.0 [7.0–10.0] |
| AdonisJS | v24.15.0 | upstream | 1000 | 3/3 | 115.0 [114.8–115.5] | 208.4 [203.9–221.8] | 212.1 [206.0–223.5] | 37.8 [35.6–38.7] | 15.0 [15.0–17.0] |
| NestJS · Express | v24.15.0 | hello | 100 | 3/3 | 99.8 [99.7–100.9] | 126.2 [125.2–130.1] | 126.4 [125.2–130.1] | 2.1 [2.1–2.2] | 7.0 [7.0–8.0] |
| NestJS · Express | v24.15.0 | catalog | 100 | 3/3 | 100.3 [99.8–100.4] | 127.1 [127.0–127.7] | 127.3 [127.0–127.8] | 2.5 [2.5–2.6] | 10.0 [10.0–10.0] |
| NestJS · Express | v24.15.0 | validate | 100 | 3/3 | 100.4 [100.3–101.0] | 130.0 [129.3–130.4] | 130.5 [130.5–130.9] | 2.4 [2.3–2.4] | 9.0 [8.0–13.0] |
| NestJS · Express | v24.15.0 | upstream | 100 | 3/3 | 102.4 [101.9–102.9] | 188.1 [183.4–189.5] | 190.1 [185.1–192.4] | 6.2 [6.1–6.2] | 20.0 [20.0–22.0] |
| NestJS · Express | v24.15.0 | hello | 1000 | 3/3 | 100.4 [99.3–101.3] | 129.6 [129.4–130.0] | 129.8 [129.4–130.2] | 8.5 [8.5–8.6] | 5.0 [5.0–13.0] |
| NestJS · Express | v24.15.0 | catalog | 1000 | 3/3 | 100.8 [100.3–101.1] | 129.2 [127.9–132.9] | 129.4 [129.2–132.9] | 11.4 [11.3–11.5] | 11.0 [8.0–11.0] |
| NestJS · Express | v24.15.0 | validate | 1000 | 3/3 | 101.3 [101.2–101.4] | 132.2 [131.7–132.7] | 132.2 [131.7–132.7] | 10.7 [10.7–11.0] | 7.0 [6.0–8.0] |
| NestJS · Express | v24.15.0 | upstream | 1000 | 3/3 | 103.0 [101.1–103.4] | 201.2 [201.0–201.7] | 201.2 [201.1–201.7] | 37.1 [31.8–38.3] | 16.0 [16.0–17.0] |
| Total.js 5 | v24.15.0 | hello | 100 | 3/3 | 63.1 [63.0–63.2] | 94.6 [93.9–95.2] | 103.2 [103.1–104.0] | 1.6 [1.5–1.6] | 5.0 [5.0–6.0] |
| Total.js 5 | v24.15.0 | catalog | 100 | 3/3 | 63.3 [63.3–63.5] | 99.9 [99.9–100.7] | 107.5 [107.2–108.8] | 2.0 [1.9–2.1] | 7.0 [6.0–8.0] |
| Total.js 5 | v24.15.0 | validate | 100 | 3/3 | 63.2 [63.2–63.2] | 93.4 [92.2–94.2] | 96.7 [94.7–101.4] | 1.9 [1.8–2.0] | 7.0 [6.0–7.0] |
| Total.js 5 | v24.15.0 | upstream | 100 | 3/3 | 69.5 [69.4–69.5] | 168.3 [166.0–169.2] | 169.8 [167.4–172.5] | 5.6 [5.4–5.6] | 18.0 [18.0–18.0] |
| Total.js 5 | v24.15.0 | hello | 1000 | 3/3 | 62.8 [62.8–63.2] | 165.7 [164.9–166.7] | 173.8 [173.1–174.3] | 8.2 [8.1–8.2] | 6.0 [6.0–6.0] |
| Total.js 5 | v24.15.0 | catalog | 1000 | 3/3 | 63.3 [63.3–63.5] | 175.0 [173.3–175.6] | 175.5 [173.7–181.0] | 9.9 [9.9–9.9] | 6.0 [5.0–9.0] |
| Total.js 5 | v24.15.0 | validate | 1000 | 3/3 | 63.2 [63.0–63.5] | 169.2 [164.2–169.4] | 171.4 [170.9–171.4] | 9.1 [9.0–9.2] | 22.0 [6.0–27.0] |
| Total.js 5 | v24.15.0 | upstream | 1000 | 3/3 | 68.4 [68.1–69.2] | 205.0 [203.3–206.0] | 207.9 [203.8–210.7] | 36.4 [30.2–36.8] | 23.0 [22.0–24.0] |

[Mediciones originales](/benchmarks/linux-20261017/general.json)

[Fuentes congeladas y dependencias fijadas](/benchmarks/linux-20261017/sources.tar.gz)

[Informe registrado](/benchmarks/linux-20261017/general-report.md)

[CSV por escenario](/benchmarks/linux-20261017/general.csv)

## Reproducir y comprobar

Utiliza una carpeta vacía con Docker (contenedores Linux), curl y tar. No necesitas Node.js en tu equipo: la comprobación de hash y las pruebas utilizan Node 24.15.0 dentro de Docker. La primera compilación descarga dependencias y construye Meteor, por lo que puede tardar varios minutos. La preparación requiere internet; los contenedores de pruebas no tienen red exterior. Cada escenario medido tarda unos seis minutos.

El kit completo ejecuta los ocho adaptadores con Node 24.15.0 en contenedores Linux. Incluye el programa de pruebas, los adaptadores, los locks y la compilación de Meteor. Las mediciones publicadas conservan las versiones y las fuentes originales, disponibles en la evidencia; este kit unifica las nuevas ejecuciones.

[Descargar el kit completo de pruebas](https://forge.totaljs.es/benchmarks/node-24.15.0/sources.tar.gz)

1. Descargar y preparar. El enlace incluye el programa de pruebas, los adaptadores y los locks; no necesitas instalar Forge ni clonar un repositorio. Desde una carpeta vacía, ejecuta estos comandos. Si descargas con el botón, conserva el nombre sources.tar.gz y omite curl.

```bash
curl --fail --location --output sources.tar.gz 'https://forge.totaljs.es/benchmarks/node-24.15.0/sources.tar.gz' &&
docker run --rm --platform linux/amd64 --network none -v "$PWD:/kit:ro" node:24.15.0-bookworm node -e 'const fs=require("node:fs"),crypto=require("node:crypto");if(crypto.createHash("sha256").update(fs.readFileSync("/kit/sources.tar.gz")).digest("hex")!=="65801cd865a3fc961e69ba8df421ed198acdc399d29934714fb954e4de1db651")throw Error("SHA-256 mismatch");' &&
tar -xzf sources.tar.gz &&
docker build --platform linux/amd64 -t forge-benchmark-local . &&
mkdir -p results
```

2. Comprobar la instalación (unos 15–30 segundos). Esta prueba breve genera smoke.json y verifica sus entradas; no es un resultado de rendimiento publicable.

```bash
docker run --rm --platform linux/amd64 --cpus 2 --memory 2g --memory-swap 2g --pids-limit 256 --read-only --network none --user "$(id -u):$(id -g)" --tmpfs /tmp:rw,nosuid,nodev,size=512m,mode=1777 -v "$PWD/results:/results" forge-benchmark-local node benchmarks/v2/run.cjs --smoke --frameworks totaljs --workloads hello --rates 1000 --out /results/smoke.json
docker run --rm --platform linux/amd64 --cpus 2 --memory 2g --memory-swap 2g --pids-limit 256 --read-only --network none --user "$(id -u):$(id -g)" --tmpfs /tmp:rw,nosuid,nodev,size=512m,mode=1777 -v "$PWD/results:/results" forge-benchmark-local node benchmarks/v2/verify.cjs /results/smoke.json --allow-smoke
```

3. Ejecutar y verificar la medición elegida. El resultado se guarda en results/my-run.json dentro de la carpeta benchmarks seleccionada. El programa no sobrescribe archivos existentes: usa otro nombre para repetir. La verificación comprueba integridad y entradas, no que las cifras coincidan con las publicadas.

```bash
docker run --rm --platform linux/amd64 --cpus 2 --memory 2g --memory-swap 2g --pids-limit 256 --read-only --network none --user "$(id -u):$(id -g)" --tmpfs /tmp:rw,nosuid,nodev,size=512m,mode=1777 -v "$PWD/results:/results" forge-benchmark-local node benchmarks/v2/run.cjs --frameworks totaljs --workloads hello --rates 1000 --seconds 60 --warmup 15 --rest 30 --reps 3 --connections 32 --out /results/my-run.json
docker run --rm --platform linux/amd64 --cpus 2 --memory 2g --memory-swap 2g --pids-limit 256 --read-only --network none --user "$(id -u):$(id -g)" --tmpfs /tmp:rw,nosuid,nodev,size=512m,mode=1777 -v "$PWD/results:/results" forge-benchmark-local node benchmarks/v2/verify.cjs /results/my-run.json
```

[JSON](/benchmarks/summary.json) · [Revisión de integridad y entorno](/benchmarks/linux-20261017/review.json) · [SHA-256](/benchmarks/linux-20261017/SHA256SUMS.txt)
