Loading home…
Loading home…
Loading article…
Si cada nueva funcionalidad te obliga a modificar cinco servicios distintos, probablemente tengas un problema de acoplamiento. Aprende cómo Event-Driven Architecture ayuda a desacoplar módulos y escalar aplicaciones NestJS.

Sin spam — solo un aviso cuando publique algo nuevo sobre backend, cloud y arquitectura.
Un email cuando salga un artículo. Puedes darte de baja cuando quieras.

Controladores que saben demasiado, entidades llenas de decoradores ORM y tests que exigen base de datos. Guía práctica de puertos y adaptadores en NestJS.

Cuando tu UserService atiende POST y GET, optimizar un lado rompe el otro. Comandos, consultas y handlers con @nestjs/cqrs, sin humo.

Si agregar un nuevo cliente implica desplegar una nueva aplicación o copiar una base de datos completa, probablemente tu arquitectura SaaS no está preparada para escalar. Aprende cómo implementar multi-tenancy en NestJS de forma limpia y mantenible
Llega un momento en toda aplicación en crecimiento donde un simple caso de uso empieza a convertirse en una cadena de responsabilidades difícil de mantener.
Imagina el proceso de registro de usuarios.
Al principio parece sencillo:
await userRepository.create(user);
Meses después, el mismo flujo termina haciendo algo parecido a esto:
await userRepository.create(user);
await emailService.sendWelcomeEmail(user);
await auditService.registerUserCreation(user);
await analyticsService.trackNewUser(user);
await crmService.createContact(user);
await notificationService.notifyAdmins(user);
El problema no es el código.
El problema es que tu módulo de usuarios ahora conoce demasiadas cosas.
Sabe cómo enviar correos.
Sabe cómo registrar auditorías.
Sabe cómo actualizar métricas.
Sabe cómo integrarse con sistemas externos.
Cada nueva integración aumenta el acoplamiento.
Cada nuevo requerimiento obliga a modificar código que ya funcionaba.
Y eventualmente algo tan simple como registrar un usuario se convierte en una operación de alto riesgo.
Aquí es donde entra Event-Driven Architecture.
Cuando analizamos sistemas que se vuelven difíciles de mantener, normalmente encontramos el mismo patrón:
UserService
├── EmailService
├── AuditService
├── AnalyticsService
├── CRMService
└── NotificationService
Cada dependencia adicional aumenta:
La consecuencia es que un cambio aparentemente pequeño termina afectando múltiples áreas del sistema.
En lugar de ejecutar todas las acciones directamente, el módulo publica un evento.
UserService
│
▼
UserCreatedEvent
│
┌────┼────┬─────┐
▼ ▼ ▼ ▼
Email Audit CRM Analytics
El servicio ya no necesita conocer quién consume el evento.
Solo comunica algo que ocurrió.
this.eventBus.publish(
new UserCreatedEvent(user.id, user.email),
);
Nada más.
Un error común es modelar eventos como comandos.
Mal:
SendWelcomeEmailEvent
Bien:
UserCreatedEvent
La diferencia es importante.
Los eventos describen algo que ya ocurrió.
No expresan una intención.
Piensa en ellos como hechos del negocio.
UserCreatedEvent
OrderPaidEvent
InvoiceGeneratedEvent
SubscriptionCanceledEvent
NestJS incluye soporte nativo para eventos mediante CQRS.
Definimos el evento:
export class UserCreatedEvent {
constructor(
public readonly userId: string,
public readonly email: string,
) {}
}
Publicamos el evento:
this.eventBus.publish(
new UserCreatedEvent(
user.id,
user.email,
),
);
Creamos un handler:
@EventsHandler(UserCreatedEvent)
export class SendWelcomeEmailHandler
implements IEventHandler<UserCreatedEvent>
{
async handle(event: UserCreatedEvent) {
await this.emailService.sendWelcomeEmail(
event.email,
);
}
}
Ahora el módulo de usuarios ya no sabe nada sobre correos electrónicos.
Esta es una de las ventajas más importantes.
Un mismo evento puede ser consumido por varios módulos.
UserCreatedEvent
├── SendWelcomeEmailHandler
├── RegisterAuditHandler
├── SyncCRMHandler
└── GenerateMetricsHandler
Y el productor no necesita modificarse.
No todo debe convertirse en un evento.
Los eventos son especialmente útiles cuando:
Por ejemplo:
✅ Registro de usuarios
✅ Creación de órdenes
✅ Generación de facturas
✅ Actualización de inventario
✅ Notificaciones
Si una operación es estrictamente necesaria para completar una transacción:
CreateOrder
└── ValidateStock
No la conviertas en evento.
Forma parte del flujo principal.
Los eventos son excelentes para desacoplar.
No son una excusa para ocultar lógica crítica.
| Beneficio | Impacto |
|---|---|
| Menor acoplamiento | Menos cambios cruzados |
| Escalabilidad | Nuevos consumidores sin tocar el productor |
| Mantenibilidad | Código más simple |
| Reutilización | Un evento alimenta múltiples procesos |
| Evolución | Integraciones independientes |
Si ya aplicas Arquitectura Hexagonal, los eventos encajan de forma natural.
El dominio genera eventos.
La aplicación los publica.
Los adaptadores reaccionan.
Esto mantiene el núcleo de negocio limpio y libre de dependencias externas.
Muchos equipos intentan resolver problemas de escalabilidad agregando más servicios.
La mayoría de las veces el problema no es la cantidad de servicios.
Es la cantidad de dependencias entre ellos.
Event-Driven Architecture permite que los módulos colaboren sin conocerse.
Y cuando un sistema deja de depender de llamadas directas para cada integración, la velocidad de desarrollo aumenta y el mantenimiento deja de convertirse en una pesadilla.
Si tu UserService envía correos, registra auditorías, actualiza métricas y sincroniza sistemas externos, probablemente no necesitas otro servicio.
Probablemente necesitas eventos.