En esta guía completa encontrarás preguntas y respuestas frecuentes sobre backend enfocadas en Node.js, Express, MongoDB, autenticación y diseño de sistemas, ideal para entrevistas técnicas y para mejorar tus desarrollos con buenas prácticas. También presentamos cómo Q2BSTUDIO puede ayudarte con aplicaciones a medida y soluciones en inteligencia artificial, ciberseguridad y servicios cloud.
Node.js núcleo Node.js es single threaded para el hilo de eventos, pero maneja múltiples peticiones eficientemente usando I/O no bloqueante y el event loop. El event loop coordina fases: timers, pending callbacks, idle/prepare, poll, check y close callbacks. Las operaciones de I/O se delegan a libuv y al sistema operativo; cuando una operación termina se encola un callback para ejecutar en el hilo principal. Microtasks y macrotasks: microtasks incluyen Promises y process.nextTick; macrotasks incluyen setTimeout, setInterval y I/O callbacks. Diferencia entre process.nextTick y setImmediate: nextTick se ejecuta antes de que el event loop pase a la siguiente fase, setImmediate se ejecuta en la fase check tras polling. Para manejar 1000 peticiones concurrentes Node.js mantiene conexiones ligeras y procesa callbacks hablando con el OS, pero task CPU intensivas deben sacarse del hilo principal mediante worker threads, child processes o colas externas.
Fases del event loop Timers ejecuta callbacks de setTimeout/setInterval cuyo tiempo ha expirado. Pending callbacks ejecuta callbacks de algunas APIs del sistema. Idle, prepare internas de libuv. Poll espera nuevas I/O y ejecuta callbacks de I/O. Check es donde se ejecutan setImmediate. Close callbacks son callbacks de cierre como socket.onclose. El orden y la prioridad puede cambiar según microtasks que se vacían tras cada callback. Ejemplo práctico de orden de ejecución: sincronía > microtasks (Promises, process.nextTick) > macrotasks según fase.
Procesamiento CPU intensivo No bloquear el event loop: usar worker threads para cálculos pesados, child processes o delegar a servicios externos; usar clustering para aprovechar múltiples núcleos. En child_process: fork crea un proceso Node con canal IPC, spawn lanza un proceso y stream de stdio sin bufferar comandos, exec ejecuta comando en shell y devuelve buffer completo, execFile ejecuta un binario directamente sin shell y es más seguro/eficiente para archivos ejecutables.
libuv es la biblioteca en C que implementa el loop de eventos, I/O asincrónico y el pool de hilos. Es la pieza clave que permite a Node abstraer operaciones del sistema y proporcionar comportamiento no bloqueante.
Streams y backpressure Streams permiten procesar datos en chunks, evitando cargar todo en memoria. Tipos: readable para lectura, writable para escritura, duplex para leer y escribir, transform para transformar datos en el flujo. Backpressure ocurre cuando el consumidor no sigue el ritmo del productor; manejarlo comprobando writable.write devuelve false y usando drain para reanudar. Caso práctico: servir archivos grandes con fs.createReadStream y pipe a la respuesta HTTP evita OOM. Diferencia entre fs.readFile y fs.createReadStream: readFile carga todo el archivo en memoria antes de devolverlo; createReadStream emite chunks y es streaming.
Depuración y rendimiento Para problemas CPU/mem usar herramientas como el inspector Node con flag --inspect, clinic, heapdump, lllprofiler, y perfiles de CPU. Detectar memory leaks analizando heap snapshots, retenciones globales o closures. Para prevenir starvation evitar bucles largos en el hilo principal, dividir trabajo en microtasks bien balanceadas y usar worker threads.
Módulos require es CommonJS y se resuelve de forma síncrona con algoritmo node_modules lookup; import es sintaxis ES Modules y puede ser asíncrona en ciertas configuraciones. package-lock.json fija versiones exactas instaladas para reproducibilidad, mientras package.json declara dependencias y metadatos.
Graceful shutdown Capturar señales SIGINT/SIGTERM, dejar de aceptar nuevas peticiones, esperar a finalizar las actuales o establecer timeout, cerrar conexiones a BD y colas antes de salir. Evitar usar uncaughtException para lógica de negocio; lo recomendado es loggear, intentar un shutdown controlado y reiniciar el proceso. Para unhandledRejection también loggear y decidir política: convertir en excepción o recuperar donde tenga sentido.
Buffers y TypedArrays Buffer es la clase Node para manejar binarios; se basa en Uint8Array pero añade métodos y compatibilidades legacy. Uint8Array es estándar Web API para arrays de bytes.
Seguridad Buenas prácticas: validar entradas, usar HTTPS, escudo con headers de seguridad tipo Helmet, rate limiting para evitar abuso, escaneo de dependencias, y pruebas de pentesting. Q2BSTUDIO ofrece servicios de ciberseguridad y pentesting para fortalecer aplicaciones a medida.
N-API facilita escribir addons nativos sin depender directamente de ABI de V8, permitiendo módulos C/C++ seguros y estables entre versiones de Node.
Monitoreo Métricas clave: latencia, RPS, error rate, uso CPU/mem, GC pauses, handles abiertos, pool de conexiones DB. Herramientas: Prometheus, Grafana, New Relic, APMs y logs centralizados. El flag --inspect permite debugging remoto y perfiles en producción con cuidado.
Express Middleware es código que procesa requests y responses en la cadena. Tipos: aplicación, router y error-handling middleware. Error-handling middleware tiene firma con cuatro parámetros para capturar errores. Para errores async usar patrones que propagan el error a next, por ejemplo un wrapper que envuelva rutas async y haga catch(next). app.use aplica middleware a la app, router.use lo hace en el contexto del router. Para subir archivos usar multer que procesa multipart/form-data en streaming y permite límites y almacenamiento temporal. Implementar CORS habilitando cabeceras apropiadas. Para rate limiting usar soluciones por IP o por key y mantener tolerancia y límites por ruta.
Internals de Express El request-response cycle recorre middlewares en orden de declaración; controlar orden es clave. res.locals sirve para compartir datos entre middlewares y vistas. Diferencia entre app.route y router.route es el contexto: app.route registra rutas en la app; router.route encapsula un conjunto de rutas reutilizable. res.send serializa según tipo, res.json fuerza JSON y añade content-type, res.end cierra la respuesta sin transformar.
Mongoose y MongoDB find devuelve array, findOne un documento, findById busca por _id. populate resuelve referencias entre colecciones. Indexing usa estructuras tipo B-tree para acelerar búsquedas; los índices compuestos dependen del orden de campos. Aggregation pipeline permite stages como match, group, project, sort, limit, skip, lookup, unwind, addFields; optimizar poniendo $match temprano y apoyándose en índices. Opciones lean devuelve POJOs sin overhead mongoose, cursor permite streaming de resultados.
Escalabilidad y datos Replica sets sirven alta disponibilidad y lecturas redundantes; sharding distribuye datos para particionado horizontal. Transacciones multi-documento ofrecen ACID en replica sets. Para almacenamiento de archivos grandes usar GridFS. Implementar soft delete con flags y plugins que filtran por defecto. Versionado de esquemas y migraciones se hacen con scripts y rollouts controlados.
Autenticación y autorización JWT: header, payload y signature. Access token de corta duración para recursos, refresh token para renovar sin re-login. Proteger tokens con httpOnly y secure cookies o almacenamiento seguro en cliente. Bcrypt para almacenar contraseñas con salt y rounds. Para OAuth 2.0 usar authorization code grant para apps web. Implementar RBAC validando claims del token y midleware de permisos. Para MFA usar TOTP y verificación paso a paso.
Escenarios prácticos Para alto volumen de archivos o emails usar colas y workers (Bull, Redis) para offload asincrónico. Para uploads grandes usar streaming y multipart chunking; para procesamiento de imágenes crear pipeline con jobs y backpressure. Cachear con Redis para lecturas frecuentes y estrategia de invalidación TTL o pub/sub para coherencia. Para queries lentas sobre millones de documentos usar índices, evitar scans, y proyectar campos necesarios. Para race conditions usar transactions, optimistic locking o reservas de stock transaccionales.
DevOps y despliegue CI/CD con GitHub Actions o Jenkins, despliegue sin downtime con blue-green o canary, usar secrets manager para variables sensibles, multi-stage Docker builds para imágenes pequeñas y readiness/liveness probes en Kubernetes. Monitoreo con PM2, Prometheus, APMs y logging centralizado con ELK.
Buenas prácticas de código y testing Revisar promesas para evitar no await, validar esquemas Mongoose, escapar output en React para evitar XSS y usar keys en listas. Testear rutas async con Jest y Supertest, mockear MongoDB con mongodb-memory-server, y separar pruebas unitarias, de integración y E2E. Mantener coverage razonable y tests idempotentes.
Algoritmos Conocimientos habituales en entrevistas incluyen LRU cache con O1 ops usando hashmap y lista doble, two sum con hashmap, reversal de listas enlazadas, validación de paréntesis con stack, debounce y throttle, binary search, tries y detección de ciclos con tortoise and hare.
Si necesitas soluciones a medida, Q2BSTUDIO desarrolla aplicaciones a medida y software a medida integrando inteligencia artificial y servicios cloud. Ofrecemos asesoría en inteligencia artificial para empresas, agentes IA y Power BI; también cubrimos servicios cloud aws y azure y servicios de inteligencia de negocio para mejorar TU producto digital.
Q2BSTUDIO combina experiencia en software, IA y ciberseguridad para entregar productos seguros, escalables y optimizados. Contáctanos para evaluar tu arquitectura, optimizar rendimiento o preparar candidatos para entrevistas técnicas con formación práctica en Node.js, Express, MongoDB, DevOps y seguridad.