Microservicio de notificaciones con DDD: patrones de producción
El crecimiento de un sistema de notificaciones suele ser silencioso. Lo que comienza como una simple función para enviar un correo al confirmar un pedido termina, meses después, convertido en una maraña de integraciones con SMS, push, Slack, Teams, preferencias de usuario, horarios de silencio, plantillas multilingües y métricas de apertura. Mantener esa lógica dispersa entre decenas de servicios acaba consumiendo al equipo de ingeniería. La solución no es añadir más código, sino aplicar una arquitectura basada en eventos con separación de dominios, siguiendo los principios de Domain-Driven Design (DDD). Este enfoque permite construir un microservicio de notificaciones que evoluciona como una plataforma, no como un conjunto de parches.
La clave está en dividir la responsabilidad de una notificación en tres capas bien diferenciadas: los eventos de dominio, que representan lo que ha ocurrido en el negocio ('pedido enviado', 'usuario mencionado', 'factura vencida'); las políticas de entrega, que determinan qué canales y bajo qué condiciones se debe notificar; y los adaptadores de canal, que se encargan de la implementación técnica de cada medio (renderizar una plantilla, llamar a la API del proveedor, registrar el envío). Esta separación evita que un cambio en un canal concreto obligue a modificar la lógica de negocio o las preferencias del usuario. El resultado es un sistema mantenible, testeable y preparado para escalar.
En la práctica, el servicio de negocio emite un evento de dominio y se desentiende. Un evento 'order.shipped' llega al bus de eventos del microservicio de notificaciones. Allí, el despachador consulta las preferencias del usuario, almacenadas en una base de datos propia o en un perfil centralizado. Estas preferencias incluyen qué canales tiene habilitados, si hay horarios de silencio, y si para ese tipo de evento concreto ha elegido solo correo electrónico. El despachador filtra, aplica las reglas de throttling o batching, y encola un trabajo por cada canal seleccionado. Cada trabajo es recogido por un trabajador especializado que conoce únicamente su canal: el trabajador de email recupera la plantilla correcta, la renderiza con los datos del usuario y la envía a través del proveedor correspondiente. Si mañana se necesita añadir un canal como WhatsApp, basta con implementar un nuevo trabajador y registrar el canal en las preferencias. El despachador no se toca.
Este patrón es especialmente valioso cuando las plantillas de notificación se gestionan como entidades de primer nivel. Almacenarlas en base de datos permite que personal de marketing o producto pueda editarlas sin necesidad de un despliegue, usando un panel de administración. Cada plantilla tiene un tipo de evento, un canal, un idioma y una versión, lo que facilita la auditoría y la recuperación ante errores. El renderizado se realiza con motores de plantillas en modo sandbox para evitar ejecución de código arbitrario. La experiencia muestra que cuando las plantillas son editables por no ingenieros, la velocidad de iteración en campañas y comunicaciones mejora drásticamente.
La superficie de cancelación de suscripción también merece un tratamiento específico. Cada notificación debe incluir un enlace de baja con un token firmado que codifique el usuario y el tipo de evento. Al hacer clic, se actualiza la preferencia correspondiente. Este mecanismo no solo es un requisito legal en muchas jurisdicciones para el marketing, sino que mejora la confianza del usuario. Además, el mismo enlace puede utilizarse en la cabecera List-Unsubscribe para que los clientes de correo ofrezcan la opción de baja con un solo clic.
Para garantizar la fiabilidad del sistema, la observabilidad debe ser un pilar desde el diseño. Cada intento de envío genera un registro de entrega con un identificador único de mensaje. Los callbacks del proveedor (entregado, rebotado, abierto, clickeado) se asocian a ese mismo identificador. De esta forma, el equipo de soporte puede consultar en segundos todo el historial de un usuario en una semana. Las métricas de apertura por plantilla e idioma se convierten en señales tempranas de problemas: una tasa de apertura inferior al diez por ciento suele indicar un asunto deficiente, un contenido irrelevante o un problema de entrega. Disponer de un panel que muestre las tendencias permite al equipo de producto tomar decisiones informadas.
En escenarios de alta concurrencia, el throttling y el batching son imprescindibles. Cuando un usuario recibe decenas de notificaciones en pocos minutos (por ejemplo, por una actividad ruidosa en una red social), el despachador puede agruparlas en un digesto programado que se envía cada cierto intervalo. Para picos de notificaciones masivas (como las generadas por la acción de un usuario muy seguido), un contador de ventana deslizante respaldado por Redis limita el flujo antes de encolar. Los trabajos que superan el umbral se redirigen a una cola de batching que, al ejecutarse, combina los eventos en una única plantilla de resumen. Este enfoque evita saturar al usuario y reduce el coste de envío.
La gestión de reintentos también debe ser inteligente. Un error 503 del proveedor de email merece un reintento con backoff; un error 400 con 'destinatario inválido' debe ir directamente a una cola de mensajes fallidos (dead-letter queue) que un humano pueda revisar. Tener un dashboard semanal de fallos por usuario ayuda a detectar problemas que de otro modo pasarían desapercibidos, como una dirección mal escrita que acumula rebotes durante meses. En Q2BSTUDIO, como empresa especializada en desarrollo de aplicaciones a medida, hemos aplicado estos patrones en múltiples proyectos, combinándolos con infraestructura en la nube y herramientas de inteligencia artificial para optimizar la personalización de los mensajes. Nuestro equipo integra servicios cloud AWS y Azure para garantizar alta disponibilidad, y aplica principios de ciberseguridad en el manejo de datos sensibles de los usuarios. Además, utilizamos Power BI para ofrecer dashboards de inteligencia de negocio que monitorizan la efectividad de las campañas, y desarrollamos agentes IA que analizan patrones de comportamiento para sugerir los mejores momentos de envío.
La adopción de un microservicio de notificaciones con DDD no es trivial: implica más código inicial que una simple llamada a sendgrid.send(). Sin embargo, la deuda técnica que se evita es enorme. Cuando el producto añade un nuevo canal, cuando los usuarios exigen preferencias más granulares, cuando los equipos de marketing necesitan editar plantillas sin esperar un deploy, el valor de tener una plataforma de notificaciones bien diseñada se amortiza en cuestión de meses. La inversión inicial se convierte en un multiplicador de la capacidad del equipo de ingeniería y en una ventaja competitiva para el negocio. En definitiva, si tu organización está gestionando más de dos tipos de notificaciones y sientes que tocar las mismas funciones cada vez que cambia un requisito, ha llegado el momento de extraer ese microservicio. Y hacerlo bien, con DDD como guía, es la diferencia entre tener un parche y tener una plataforma.
Comentarios