Talently
Talently
Express.js

Express.js

El framework Node.js minimalista para APIs y aplicaciones web

Express.js es un framework web minimalista y flexible para Node.js que provee un conjunto básico de herramientas para construir aplicaciones web y APIs. Su filosofía unopinionated otorga total libertad sobre la arquitectura, convirtiéndolo en la base de gran parte del ecosistema backend de JavaScript.

Node.jsJavaScriptRESTMiddleware

Demanda del mercado

Express.js es el framework Node.js más utilizado a nivel mundial y uno de los más descargados en npm. Tiene alta demanda en startups, agencias y empresas que trabajan con stacks JavaScript full-stack como MEAN o MERN.

Framework Node.js más usadoAlta demanda en stacks JavaScriptBase del ecosistema Node.js

Requisitos técnicos

Intermediate

Requiere buen dominio de JavaScript, programación asíncrona con Promises y async/await, y conceptos del ciclo de vida de HTTP. Familiaridad con Node.js, npm y conceptos de APIs REST es esencial para trabajar con Express en proyectos reales.

Casos de uso

Proyectos Reales

Express.js se utiliza para desarrollar:

  • APIs REST para aplicaciones web y móviles
  • Backends de aplicaciones full-stack con React o Vue
  • Microservicios ligeros con responsabilidades específicas
  • Proxies y gateways hacia otros servicios

Tipos de Empresa

Express.js es adoptado por:

  • Startups con stack JavaScript full-stack
  • Agencias digitales con proyectos Node.js
  • Empresas con equipos de desarrollo JavaScript
  • Compañías que migran backends hacia arquitecturas de microservicios

Escenarios de Producción

Express.js es ampliamente utilizado en entornos productivos como:

  • APIs REST de alto rendimiento con operaciones I/O intensivas
  • Servicios backend en arquitecturas serverless
  • Aplicaciones en tiempo real combinadas con Socket.io
  • Backends ligeros para frontends React, Vue o Angular

Escalabilidad

Express.js ofrece múltiples mecanismos para escalar aplicaciones:

  • Clustering nativo de Node.js para aprovechar múltiples cores
  • Caché con Redis para respuestas frecuentes
  • Balanceo de carga con PM2 o soluciones cloud
  • Arquitectura stateless para escalado horizontal

Ventajas y Desventajas

Ventajas

Extremadamente ligero y sin opiniones sobre la arquitectura del proyecto.

Alto rendimiento en operaciones I/O gracias al event loop de Node.js.

Ecosistema npm enorme con middleware y librerías para cualquier necesidad.

Desventajas

La falta de estructura impuesta puede generar arquitecturas inconsistentes en equipos grandes.

Requiere decisiones manuales sobre autenticación, validación y organización del código.

El manejo de errores asíncronos puede ser complejo sin las prácticas adecuadas.

Comparación

Ventajas de NestJS

  • Arquitectura estructurada con módulos, controladores y servicios
  • TypeScript como lenguaje principal
  • Inyección de dependencias integrada

Consideraciones

NestJS es la opción preferida para proyectos Node.js grandes donde la estructura y el tipado son prioritarios. Express es más adecuado para proyectos pequeños o cuando se necesita máxima flexibilidad.

Preguntas básicas

Express es preferible cuando se necesita máxima flexibilidad, el proyecto es pequeño o mediano, o el equipo quiere decidir cada pieza de la arquitectura sin convenciones impuestas. También es ideal cuando ya se domina Node.js y se quiere evitar la curva de aprendizaje de frameworks más estructurados.
El event loop de Node.js maneja múltiples conexiones concurrentes sin bloquear hilos. Esto lo hace especialmente eficiente para APIs que realizan muchas operaciones I/O como consultas a bases de datos, llamadas a APIs externas o lectura de archivos.
Express es adecuado para APIs pequeñas o medianas, prototipos rápidos o cuando el equipo prefiere definir su propia arquitectura. NestJS es preferible en proyectos grandes con equipos numerosos donde la estructura, el tipado con TypeScript y la escalabilidad del código son prioritarios.
A través de un sistema de rutas donde se define el método HTTP, la URL y el handler correspondiente. Las rutas pueden organizarse en Routers independientes que se montan en la aplicación principal, permitiendo modularizar el código.
npm gestiona todas las dependencias del proyecto. En Express la arquitectura depende casi completamente de las librerías elegidas de npm para autenticación, validación, logging y más, ya que Express no incluye estas funcionalidades por defecto.
Usando variables de entorno accesibles a través de process.env, cargadas con la librería dotenv en desarrollo mediante un archivo .env. En producción se definen directamente en el entorno del servidor o en el sistema de secretos del proveedor cloud.
En proyectos con equipos full-stack JavaScript donde el mismo lenguaje se usa en frontend y backend, en aplicaciones en tiempo real combinadas con Socket.io, o en arquitecturas serverless donde el tamaño y el tiempo de arranque del bundle son críticos.
app.use() registra middleware que se ejecuta para todas las rutas que coincidan con el path dado, independientemente del método HTTP. app.get() registra un handler específico para peticiones GET en una ruta concreta.

Preguntas técnicas

El middleware se ejecuta en el orden en que se registra con app.use(). Cada función recibe req, res y next, y debe llamar a next() para pasar al siguiente middleware. Si no llama a next() la cadena se interrumpe, lo que puede usarse para autenticación o manejo de errores.
Definiendo un middleware de error con cuatro parámetros (err, req, res, next) registrado al final de todos los middlewares. Los errores se propagan llamando a next(error) desde cualquier middleware o handler, y el manejador central formatea y devuelve la respuesta de error.
El middleware de aplicación se registra con app.use() y aplica a toda la aplicación. El middleware de router se registra en una instancia de express.Router() y solo aplica a las rutas de ese router, permitiendo modularizar la aplicación.
Separando rutas, controladores, servicios y modelos en capas independientes. Las rutas definen los endpoints, los controladores gestionan la request y response, los servicios contienen la lógica de negocio y los modelos interactúan con la base de datos.
Creando un middleware que extraiga el token del header Authorization, lo verifique con la librería jsonwebtoken y adjunte el payload decodificado a req.user. Este middleware se aplica a las rutas protegidas antes del handler de la ruta.
Usando librerías como Joi, Zod o express-validator para definir esquemas de validación. La validación se implementa como middleware antes del handler de la ruta, devolviendo errores estructurados si los datos no cumplen el esquema.
Envolviendo los handlers en un wrapper que capture errores de promesas rechazadas y los pase a next(error), o usando librerías como express-async-errors. Sin esto, las excepciones en handlers async no son capturadas por el manejador de errores de Express.
Usando helmet para cabeceras de seguridad HTTP, cors para controlar orígenes permitidos, rate limiting con express-rate-limit para prevenir abuso, y validación estricta de inputs. También deshabilitando la cabecera X-Powered-By que revela que se usa Express.

Preguntas avanzadas

Cuando el equipo crece, la base de código se vuelve difícil de mantener por falta de estructura, o cuando TypeScript y la inyección de dependencias aportarían valor real. La migración puede ser gradual montando NestJS sobre Express e incrementalmente moviendo módulos.
Usando Winston o Pino para logging estructurado en JSON, añadiendo correlation IDs a cada request para trazar flujos completos, exponiendo métricas con prom-client para Prometheus e integrando con herramientas de APM como Datadog o New Relic.
Con express-rate-limit para límites básicos por IP, Redis como store compartido en entornos multi-instancia para que los límites sean consistentes, y reglas diferenciadas por endpoint según su sensibilidad o coste computacional.
Usando express.Router() para encapsular cada módulo con sus rutas, middlewares y handlers, y exportándolos como funciones que reciben opciones de configuración. Esto permite componer la aplicación montando módulos independientes con app.use().
Usando clustering con el módulo cluster o PM2 para aprovechar múltiples cores, caché de respuestas con Redis para endpoints costosos, compresión de respuestas con el middleware compression, y profiling con clínica.js o 0x para identificar cuellos de botella.
Definiendo una arquitectura de capas documentada, usando TypeScript para tipado estático, ESLint y Prettier para estilo consistente, testing obligatorio con Jest para servicios y tests de integración para endpoints, y revisiones de código con checklist de arquitectura.

Errores comunes en entrevistas

Los errores en handlers async sin wrapper o sin express-async-errors no llegan al manejador central de errores. Es uno de los bugs más frecuentes en APIs Express y refleja falta de comprensión del ciclo de vida del middleware.
Desplegar una API Express sin helmet, sin rate limiting o sin validación de inputs es un riesgo de seguridad real. No conocer estas prácticas básicas refleja inexperiencia llevando aplicaciones Express a producción.
Poner lógica de negocio directamente en los handlers de rutas genera código difícil de testear y mantener. En entrevistas se espera conocer patrones de organización como la separación en controladores y servicios.
Elegir Express por defecto sin evaluar alternativas modernas refleja falta de criterio. En entrevistas mid-senior se espera conocer cuándo Express es la opción correcta y cuándo NestJS o Fastify serían más adecuados.
Ejecutar operaciones síncronas bloqueantes en handlers Express bloquea el event loop y degrada el rendimiento para todas las conexiones concurrentes. No entender este mecanismo refleja una comprensión superficial de Node.js.
Usar console.log en producción sin logging estructurado hace imposible la observabilidad y el diagnóstico de problemas. No conocer Winston, Pino o la importancia de correlation IDs refleja poca experiencia en entornos productivos reales.