¿Tu servidor Node.js se siente lento bajo carga y no sabes por qué? La clave suele estar en el event loop bloqueado. Aquí verás cómo detectarlo con NSolid y cómo refactorizar tu código para que las operaciones costosas no tumben el rendimiento de toda tu aplicación.
Esta guía te sirve si trabajas con servidores Express, manejas archivos JSON grandes o quieres aprender a medir el rendimiento real de tu API antes de mandarla a producción.
Qué es NSolid y cómo conectarlo a tu proceso
NSolid es una herramienta de observabilidad para Node.js gratuita en desarrollo, con monitoreo hasta para cuatro procesos. El runtime es open source y el modelo de observabilidad del SaaS no te cuesta nada para empezar [00:14].
Para conectarte, entra a accounts.nsolid.com, inicia sesión con Google, GitHub o correo, y copia tu NSolid SaaS token. Ese token es el puente entre tu proceso local y el dashboard donde vas a ver las métricas en vivo.
¿Qué es el NSolid SaaS token? Es la credencial que conecta tu proceso de Node.js con el dashboard de observabilidad de NSolid. Sin él, tus métricas no llegan al panel.
Cómo montar un endpoint bloqueante para experimentar
Para entender el problema, necesitas verlo en acción. La idea es crear un servidor con Express que tenga dos rutas: una rápida y otra que procese un JSON enorme de forma síncrona [02:00].
El flujo del experimento es así:
- Lees un archivo JSON grande de forma asíncrona con
node:fs y lo parseas una sola vez al arrancar.
- Defines un endpoint
/fast que solo responde un texto corto.
- Defines un endpoint
/block que recorre todo el JSON con un for...of y empuja cada ítem a un arreglo de resultados.
Ese for...of sobre miles de objetos es una operación síncrona y costosa. Mientras corre, nada más puede ejecutarse en ese hilo. Ese es justamente el síntoma que vamos a observar.
Cómo ejecutar tu app con NSolid Quickstart
La forma más directa es usar nsolid-quickstart vía npx, pnpm dlx o tu gestor favorito [05:00]. El comando recibe dos parámetros importantes: --saas con tu token y --exec con la ruta del archivo a ejecutar.
Apenas lo lanzas, NSolid abre el dashboard en el navegador y empieza a recolectar métricas del proceso en tiempo real. Ten paciencia: hay un delay de 20 a 25 segundos entre la recolección y lo que ves en pantalla [09:00].
Cómo medir el rendimiento real con Autocannon
Observar sin carga no sirve de mucho. Aquí entra Autocannon, una herramienta de load testing que dispara peticiones masivas a tu endpoint y te devuelve estadísticas concretas: requests totales, latencia mínima, promedio y percentil 1 %.
Los números del experimento hablan solos:
- 20 segundos de carga sobre
/fast: 382 000 requests atendidos sin despeinar el event loop.
- 20 segundos de carga sobre
/block: apenas 14 000 requests, con el event loop completamente saturado.
En el dashboard de NSolid se ve el contraste con tres métricas clave: uso de CPU, uso del event loop y heap used (memoria). Durante la carga a /fast, el event loop lag se mantuvo en 0,5, señal de salud. Durante la carga a /block, el lag se disparó y el servidor dejó de atender peticiones nuevas.
¿Qué es el event loop lag? Es el tiempo que una tarea espera para entrar al event loop. Si crece, significa que tu proceso está bloqueado y los usuarios sufren latencia.
Cómo desbloquear el event loop con setImmediate
La solución no es eliminar el trabajo pesado, sino trocearlo. En lugar de procesar los miles de objetos en un solo tick, procesas un chunk a la vez y le devuelves el control al event loop entre chunk y chunk.
El patrón se arma con tres ingredientes [11:30]:
- Un
index que recuerda por dónde vas y un chunkSize (por ejemplo, 1000).
- Una función que calcula el
end con Math.min(index + chunkSize, largeFile.length) y procesa solo ese rango.
- Una llamada a
setImmediate que reprograma la función para el siguiente ciclo, hasta terminar.
setImmediate se ejecuta en una fase del event loop posterior a I/O, lo que permite atender otras peticiones entre chunk y chunk. Es exactamente lo que necesitas para mantener vivo el endpoint rápido mientras el lento sigue trabajando en segundo plano.
Qué cambia en las métricas al refactorizar
Lanzando carga simultánea a /fast y al nuevo /unblock durante 20 segundos, los resultados se invierten:
/fast recupera capacidad y atiende 269 000 requests (antes, con /block corriendo en paralelo, solo lograba 34 000).
/unblock atiende menos, alrededor de 3 000 requests, pero no asfixia al resto del sistema.
- La CPU sube, pero el event loop nunca se bloquea.
El trade off es claro: las operaciones lentas se difieren en el tiempo, pero las rápidas siguen fluyendo. Para un servidor que atiende muchos usuarios concurrentes, esa es la diferencia entre una app usable y una caída.
Conceptos y herramientas que aparecieron en la clase
Para que puedas profundizar por tu cuenta, estos son los puntos técnicos a los que vale la pena volver:
- NSolid [00:14]: runtime y dashboard para observar procesos Node.js en producción y desarrollo.
- Express [02:30]: framework para construir el servidor web del experimento.
- Autocannon [07:00]: herramienta de load testing que mide requests por segundo y latencia.
- Event loop lag [09:30]: métrica que delata si tu proceso está bloqueado.
- setImmediate [11:00]: API de Node.js para diferir trabajo y liberar el event loop.
- Procesamiento por chunks [12:00]: técnica para partir tareas síncronas largas en piezas pequeñas.
¿Has medido alguna vez el event loop lag de tu API en producción? Cuéntame en los comentarios qué herramientas usas y qué resultados te ha dado.