Express.js
Performance y load testing
Explica cómo medir throughput, latencia y saturación, diseñar pruebas de carga realistas y localizar cuellos en Express.js y sus dependencias.
- Última actualización
- Actualizada
- Nivel
- Profundización
Express.js
Explica cómo medir throughput, latencia y saturación, diseñar pruebas de carga realistas y localizar cuellos en Express.js y sus dependencias.
Rendimiento no es “hacer Express más rápido”. Es medir dónde se consume tiempo y recursos bajo una carga representativa, y mejorar el cuello de botella sin romper el contrato.
Una request atraviesa varias etapas:
red → parser → middleware → lógica → PostgreSQL/servicios → serialización → redLa latencia total es la suma de espera y ejecución. Optimizar una etapa irrelevante no cambia la experiencia.
Mide bajo carga estable y registra el ambiente.
Node ejecuta JavaScript en un thread principal. Trabajo CPU-bound bloquea otras requests:
Event loop lag revela retraso. Para CPU real usa profiling y, si aplica, worker threads o servicios especializados.
async permite esperar I/O sin bloquear JavaScript, pero demasiadas operaciones simultáneas saturan:
La concurrencia debe limitarse según la dependencia más estrecha.
Una prueba necesita modelo de tráfico:
Mil GET /health no predicen creación de pedidos.
Carga pequeña para validar escenario y medición.
Carga esperada sostenida.
Aumenta hasta degradación para encontrar capacidad.
Incremento brusco.
Horas para detectar fugas, bloat y acumulación.
Determina cuántas instancias se necesitan para un SLO.
Un generador que espera cada respuesta antes de enviar la siguiente puede ocultar latencia durante saturación. Usa herramientas y configuración que modelen tasa de llegada real.
JIT, pools y caches cambian al inicio. Separa warm-up de medición, pero también prueba cold starts cuando el entorno los tiene.
// conceptual k6
export const options = {
scenarios: {
orders: {
executor: 'constant-arrival-rate',
rate: 100,
timeUnit: '1s',
duration: '10m',
preAllocatedVUs: 50,
},
},
};La tasa debe ajustarse a capacidad y entorno; el ejemplo no es un objetivo universal.
Queries lentas, N+1, locks, pool waiting, falta de índices.
Timeouts, retries y límites.
Responses gigantes y objetos profundos.
Logging de bodies, validación costosa o cadenas excesivas.
CPU throttling, proxy, DNS, TLS o red.
p99 sube
→ revisar saturación
→ traces lentas
→ span dominante
→ profile/query plan
→ hipótesis
→ cambio
→ repetir pruebaNo optimices a partir de intuición únicamente.
Cuando la capacidad se supera, es mejor rechazar o limitar que acumular espera infinita:
La degradación controlada protege el sistema.
Observa heap, RSS, GC y crecimiento por request. Una fuga puede venir de listeners, caches sin límite, contextos retenidos o buffers.
Un soak test ayuda. Usa heap snapshots con cuidado en producción.
POST /orders incumple p95:
Documenta qué recurso intercambias.
Idealmente similar a producción en:
No ejecutes stress destructivo sobre producción sin plan explícito.
El resultado útil no es “20k RPS”, sino:
con 2 instancias, 120 RPS sostenidos
p95 < 300ms, errores < 0.1%
con margen de 40%Incluye límites y supuestos.
Mantén pruebas pequeñas de regresión en CI y campañas completas antes de cambios críticos. Los benchmarks demasiado frágiles generan ruido.
Caching HTTP y de aplicación reduce trabajo repetido a cambio de invalidación y consistencia.