Las entrevistas de Node.js comienzan con el event loop y el código asíncrono, y luego avanzan hacia APIs, manejo de errores, streams, rendimiento y seguridad. La razón más común por la que los candidatos tropiezan es describir el event loop como si fuera magia. Una explicación clara de qué se ejecuta dónde y qué lo bloquea es lo que los entrevistadores buscan.
A continuación, 24 preguntas con respuestas. Los ejemplos de código son cortos para que puedas escribirlos de memoria.
Event loop y asincronía
1. ¿Qué es Node.js?
Un entorno de ejecución de JavaScript construido sobre el motor V8 de Chrome que se ejecuta fuera del navegador. Utiliza un event loop de un solo hilo para JavaScript con I/O no bloqueante, lo que lo hace ideal para manejar muchas conexiones que pasan la mayor parte del tiempo esperando.
2. ¿Cómo funciona el event loop?
El código JavaScript se ejecuta en un solo hilo. Cuando inicia una operación de I/O, como leer un archivo o hacer una petición, Node se la delega al sistema o a un pool de hilos y continúa. Cuando la operación termina, su callback se encola y el event loop lo ejecuta cuando la pila de llamadas está vacía. El loop pasa por fases: timers, callbacks pendientes, poll (I/O), check (setImmediate) y callbacks de cierre.
3. ¿Cuál es el orden de process.nextTick, Promises, setTimeout y setImmediate?
console.log('1 sync');
setTimeout(() => console.log('4 timeout'), 0);
setImmediate(() => console.log('5 immediate'));
Promise.resolve().then(() => console.log('3 promise'));
process.nextTick(() => console.log('2 nextTick'));
El código síncrono se ejecuta primero. Luego los callbacks de process.nextTick, después las microtareas de las promesas y luego las fases del loop. setTimeout(0) versus setImmediate puede variar en el módulo principal, pero dentro de un callback de I/O setImmediate siempre se ejecuta primero. Prepárate para explicarlo, no solo para recitarlo.
4. ¿Qué significa "bloquear el event loop" y cómo se evita?
Una tarea síncrona larga, como parsear un JSON enorme, un bucle grande o fs.readFileSync dentro de un handler de petición, detiene todas las demás peticiones hasta que termina. Se evita usando APIs asíncronas, dividiendo el trabajo en fragmentos o moviendo el trabajo intensivo de CPU a worker threads o a otro proceso.
5. Callbacks, promesas y async/await: ¿cuáles son las diferencias?
Los callbacks son el estilo original y pueden anidarse profundamente. Las promesas representan un valor futuro y se encadenan con then. async/await es azúcar sintáctico sobre las promesas que se lee como código síncrono y funciona con try/catch.
6. ¿Cómo se ejecutan tareas asíncronas en paralelo?
const [user, orders] = await Promise.all([getUser(id), getOrders(id)]);
Promise.all rechaza si alguna falla. Promise.allSettled espera a todas y reporta cada resultado. Promise.race devuelve la primera que se resuelva. No uses await dentro de un bucle cuando las llamadas son independientes.
7. ¿Cuál es la diferencia entre worker threads, procesos hijos y cluster?
Los worker threads ejecutan JavaScript en hilos separados dentro de un mismo proceso y pueden compartir memoria, lo que los hace adecuados para trabajo intensivo de CPU. Los procesos hijos inician programas separados. El módulo cluster crea varias copias de la aplicación, una por núcleo, compartiendo un puerto, para que puedas usar todas las CPUs al manejar peticiones.
Módulos y herramientas
8. ¿CommonJS versus módulos ES?
CommonJS usa require y module.exports y carga de forma síncrona. Los módulos ES usan import y export, son el estándar en JavaScript y soportan top-level await. Node soporta ambos, y se elige según la extensión del archivo o el campo type en package.json.
9. ¿Qué contiene package.json y cuál es la diferencia entre dependencies y devDependencies?
Contiene metadatos, scripts y dependencias. dependencies se necesitan en tiempo de ejecución, y devDependencies solo para desarrollo y pruebas. Un archivo de lock registra las versiones exactas para que las instalaciones sean reproducibles.
10. ¿Cómo se maneja la configuración del entorno?
Usa variables de entorno, leídas a través de process.env, con un módulo de configuración validado. Mantén los secretos fuera del repositorio y usa un gestor de secretos en producción.
APIs y Express
11. ¿Qué es un middleware en Express?
Una función con acceso a la petición, la respuesta y next. Los middleware se ejecutan en orden y pueden modificar la petición, terminar la respuesta o ceder el control. Los usos típicos son logging, parseo del body, autenticación y manejo de errores.
app.use((req, res, next) => {
console.log(req.method, req.url);
next();
});
12. ¿Cómo se manejan los errores en una aplicación Express?
Captura los errores en los handlers asíncronos y pásalos a next(err), luego usa un middleware de manejo de errores con cuatro argumentos (err, req, res, next) para enviar una respuesta consistente. En Express 5, las promesas rechazadas de los handlers se reenvían automáticamente. Para las excepciones no capturadas y los rechazos no manejados, registra el error y reinicia el proceso en lugar de continuar en un estado desconocido.
13. ¿Cómo diseñarías un endpoint REST para crear un pedido?
Valida la entrada, autentica al usuario, verifica los permisos, crea el pedido dentro de una transacción de base de datos, devuelve 201 con el nuevo recurso y su ubicación, maneja los duplicados con una clave de idempotencia y devuelve errores claros con los códigos de estado adecuados.
14. ¿Cómo se autentica a los usuarios?
Con sesiones mediante cookies o con tokens como los JWT. Hashea las contraseñas con un algoritmo lento como bcrypt o argon2. Con los JWT, mantén una expiración corta, usa tokens de refresco con cuidado y no guardes datos sensibles en el token.
Streams, archivos y rendimiento
15. ¿Qué son los streams y por qué usarlos?
Los streams procesan datos en fragmentos en lugar de cargarlos todos en memoria. Los tipos son readable, writable, duplex y transform. Úsalos para archivos grandes, cargas y descargas.
const fs = require('node:fs');
const { pipeline } = require('node:stream/promises');
const zlib = require('node:zlib');
await pipeline(fs.createReadStream('in.log'), zlib.createGzip(), fs.createWriteStream('in.log.gz'));
16. ¿Qué es la contrapresión (backpressure)?
Cuando un stream de escritura no puede seguir el ritmo de uno de lectura, le indica a la fuente que reduzca la velocidad. pipeline y pipe se encargan de esto por ti. Si escribes manualmente, revisa el valor de retorno de write() y espera el evento drain.
17. ¿Cómo encuentras una fuga de memoria?
Observa la memoria a lo largo del tiempo, toma instantáneas del heap (Chrome DevTools o --inspect) y compáralas para ver qué objetos crecen. Las causas comunes son cachés globales que nunca expiran, listeners de eventos que no se eliminan y closures que retienen objetos grandes.
18. ¿Cómo escalas una aplicación Node.js?
Ejecuta varios procesos con el módulo cluster o un gestor de procesos, colócalos detrás de un balanceador de carga, mantén la aplicación sin estado moviendo las sesiones a Redis o a una base de datos, usa caché y escala horizontalmente con contenedores. Mueve el trabajo intensivo de CPU a workers o a servicios separados.
19. ¿Cómo perfilas un endpoint lento?
Mide primero con logs y tiempos, luego usa --prof o --cpu-prof, o una herramienta de flame graph, para encontrar las funciones más costosas. Revisa las consultas a la base de datos, ya que la lentitud suele estar ahí más que en JavaScript.
Seguridad y confiabilidad
20. ¿Cuáles son los problemas de seguridad comunes en Node.js?
Inyección (SQL, NoSQL, comandos), cross-site scripting, autenticación débil, dependencias vulnerables, secretos en el código, falta de límites de tasa y deserialización insegura. Mitígalos con validación de entrada, consultas parametrizadas, helmet, auditorías de dependencias (npm audit) y el principio de menor privilegio.
21. ¿Cómo haces un apagado ordenado?
Ante SIGTERM, deja de aceptar nuevas conexiones, permite que las solicitudes en curso terminen, cierra las conexiones a la base de datos y luego sal, con un tiempo de espera máximo como respaldo.
process.on('SIGTERM', () => {
server.close(() => process.exit(0));
});
22. ¿Cómo pruebas código Node.js?
Pruebas unitarias con un runner como el node:test integrado, Jest o Vitest, simulando las llamadas externas. Pruebas de integración contra una base de datos de prueba y pruebas a nivel HTTP con una herramienta como Supertest. Mantén las pruebas rápidas e independientes.
Diseño y escenarios
23. Tu API es lenta bajo carga. ¿Cómo lo investigas?
Revisa las métricas de latencia y CPU. Si la CPU está alta en un solo núcleo, busca código bloqueante o trabajo pesado de JSON. Si la CPU está baja y la latencia es alta, revisa la espera en la base de datos u otros servicios. Luego agrega caché, índices, pooling de conexiones o batching, y vuelve a probar bajo carga.
24. ¿Cómo construirías un endpoint de carga de archivos grandes?
Transmite la carga directamente al almacenamiento, como almacenamiento de objetos con una URL prefirmada, en lugar de almacenarla en memoria. Establece límites de tamaño, valida el tipo, escanea si es necesario y procésala después en un trabajo en segundo plano.
Cómo prepararte
Escribe una pequeña API con autenticación, una base de datos y una ruta de carga, luego perfílala con una herramienta de carga y corrige un problema. Practica dibujar el event loop y explicar la salida de un script pequeño como el de arriba. Prepara una historia real sobre cómo depuraste un problema de rendimiento o confiabilidad. Para las rondas de código, consulta nuestra guía del asistente para entrevistas de programación, y para diseño, la guía de diseño de sistemas.
Di tus respuestas en voz alta y lee la transcripción para detectar dónde usaste un término sin explicarlo. Sigue las reglas del empleador sobre herramientas de IA en cualquier entrevista en vivo.
Practica respuestas para entrevistas de Node.js con YesToTheOffer
Realiza una entrevista técnica simulada, explica el bucle de eventos en voz alta y revisa tu transcripción después. 30 minutos gratis, sin suscripción.



