Diseña un sistema de notificaciones que distribuya un solo evento a push, correo y SMS
Un solo evento de "pedido enviado" debe convertirse en tres llamadas posteriores muy distintas — cada una con su propio proveedor, su propio modo de falla y su propia idea de un reintento aceptable.
APRENDE HACIENDOPon a prueba tu intuición3 pasos
Diseña un sistema de notificaciones que distribuya un solo evento a push, correo y SMS
Usa los ejemplos y la explicación de la lección para comprobar tu idea.
Reflexión personal. No se envía a ningún servicio de IA.#Un evento, tres problemas de entrega completamente distintos
"Distribuir una notificación a push, correo y SMS" suena a un problema de enrutamiento, pero lo interesante es que push, correo y SMS no son tres sabores de lo mismo — son tres sistemas con estructuras de costo distintas, modos de falla distintos y obligaciones regulatorias distintas. El push es casi gratis y se puede reintentar de forma agresiva. El SMS cuesta dinero real por mensaje y algunos proveedores limitan la tasa de forma estricta. El correo está en un punto intermedio, pero un error ahí puede hacer que tu dominio de envío termine en una lista negra. Tratar los tres como "simplemente enviar un mensaje a una cola" es justo donde los diseños ingenuos se caen.
Requisitos que vale la pena fijar primero:
- Un solo evento de negocio (pedido enviado, restablecimiento de contraseña, campaña promocional) puede distribuirse a cero, uno o varios canales según las preferencias del usuario (por ejemplo, suscrito a push pero no a SMS).
- Idempotencia — el mismo evento nunca debe entregarse dos veces por el mismo canal, aunque el productor reintente o el pipeline reentregue.
- Cada canal necesita manejo de reintentos y fallas independiente — un proveedor de SMS atascado no debería frenar la entrega de correos.
- Seguimiento de entrega — los equipos de producto y soporte necesitan saber, por usuario y por canal, si una notificación fue enviada, entregada, rebotada o si el usuario se dio de baja.
- Cumplimiento normativo — el correo conlleva obligaciones tipo CAN-SPAM (enlaces de baja, identificación del remitente), el SMS conlleva obligaciones de consentimiento tipo TCPA y de los operadores; las bajas deben aplicarse antes del envío, no registrarse después del hecho.
#Arquitectura
El servicio de notificaciones es el único punto de entrada: recibe un evento de negocio, consulta las preferencias del usuario objetivo y su ventana de horas de silencio, revisa el almacén de idempotencia, y entrega el trabajo a un router de fan-out que publica un mensaje por cada canal elegible en la cola propia de ese canal. A partir de ahí, cada canal es un pipeline independiente con su propio pool de workers, su propia integración con el proveedor y su propia cola de mensajes fallidos (DLQ) — un radio de impacto completamente aislado por canal.
#Idempotencia y deduplicación
Cada mensaje lleva una clave de idempotencia determinista — típicamente hash(event_id, user_id, canal) — que se verifica contra el almacén de idempotencia (una tabla de Redis o DynamoDB con un TTL un poco mayor que tu ventana máxima posible de reentrega) antes de que un worker llame a su proveedor. Esto importa porque todo el pipeline está construido sobre entrega at-least-once: el bus de eventos puede reentregar, un worker puede fallar después de enviar pero antes de confirmar, y un reintento desde un replay de la DLQ no debe convertirse en un segundo correo en la bandeja del usuario. La verificación de idempotencia — no "no esperamos duplicados" — es lo que hace seguro construir sobre at-least-once.
#Workers por canal y política de reintentos
Cada canal amerita una política de reintentos genuinamente distinta, porque el costo y la urgencia de una falla son diferentes:
| Canal | Comportamiento típico de reintento | Por qué |
|---|---|---|
| Push | Agresivo — backoff corto, varios intentos en minutos | Prácticamente gratis; un push perdido tiene bajo riesgo y a menudo lo reemplaza uno más reciente de todos modos |
| Correo | Moderado — backoff exponencial durante horas, luego DLQ | Los errores transitorios de SMTP/proveedor son comunes; un correo tardío suele estar bien, uno duplicado es vergonzoso |
| SMS | Conservador — pocos intentos, ventana corta, luego DLQ | Cuesta dinero real por intento y los límites de tasa por número son estrictos; un SMS obsoleto ("tu viaje llegó" una hora tarde) puede estar activamente equivocado |
Un mensaje que agota sus reintentos termina en la cola de mensajes fallidos (DLQ) de ese canal en vez de bloquear la cola detrás de él — un mensaje envenenado para un usuario nunca debe frenar la entrega a todos los demás. Las entradas de la DLQ alimentan las alertas y, para notificaciones de alto valor (restablecimiento de contraseña, alertas de seguridad), una ruta de reintento manual o automatizada.
#Seguimiento de entrega y el ciclo de retroalimentación
Cada worker escribe un registro de estado (en cola -> enviado -> entregado/rebotado/fallido) en un almacén de estado de entrega compartido, indexado por evento, usuario y canal. Esto cumple doble función: alimenta las consultas de soporte al cliente tipo "¿le llegó esto a mi usuario?", y cierra un ciclo de retroalimentación hacia el almacén de preferencias — el webhook de rebote de un proveedor de correo, por ejemplo, debería poder suprimir automáticamente futuros envíos a una dirección permanentemente inválida, y la respuesta "STOP" de un operador de SMS debe cambiar de inmediato la preferencia de SMS de ese usuario a "dado de baja" antes de que se intente siquiera el siguiente envío, no solo quedar registrada para una limpieza posterior.