Blogs / Cómo Funcionan los Sistemas de Notificaciones

Cómo Funcionan los Sistemas de Notificaciones

Publicado
19 de julio de 2026
Autor
Faizan Nadeem
Etiquetas
System Design Distributed Systems Kafka Push Notifications
Persona sosteniendo un teléfono
Foto de Jamie Street en Unsplash

¿Alguna vez te has preguntado cómo recibes ese ping instantáneo cuando a alguien le gusta tu publicación o te envía un mensaje? Esa simple notificación que ves en tu teléfono es el resultado de uno de los sistemas distribuidos más complejos de la ingeniería de software moderna. Lo que parece una alerta que llega en milisegundos en realidad implica múltiples servidores, bases de datos, colas de mensajes y servicios de terceros trabajando en perfecta armonía.

Después de implementar sistemas de notificaciones para aplicaciones en producción que atienden a millones de usuarios, he aprendido qué funciona realmente a escala. La mayoría de los desarrolladores piensa que las notificaciones son simples: enviar un mensaje, entregarlo y listo. Pero cuando manejas millones de notificaciones al día a través de canales de email, SMS y push, la complejidad se dispara.

En esta guía completa, aprenderás:

  • Cómo se diseñan los sistemas de notificaciones para escalar y ser confiables
  • Los componentes exactos que impulsan sistemas que manejan miles de millones de mensajes
  • Retos reales de producción y cómo resolverlos
  • Particularidades específicas de plataformas como FCM, APNs y otros servicios de entrega
  • Ejemplos de código y diagramas de arquitectura para construir tu propio sistema

Al final, tendrás un conocimiento práctico de la infraestructura de notificaciones que podrás aplicar en entrevistas de diseño de sistemas o en sistemas reales en producción. Vamos a ello.

Tabla de contenido

  1. Comprender los sistemas de notificaciones: lo básico
  2. La arquitectura completa: cómo encaja todo
  3. Explicación de los componentes principales
  4. El recorrido del mensaje: del evento a la notificación
  5. Gestión de múltiples canales de notificación
  6. Escalar a millones: desafíos de producción
  7. Detalles de implementación específicos de cada plataforma
  8. Construir tu sistema de notificaciones: ejemplos de código
  9. Errores comunes y cómo evitarlos
  10. Buenas prácticas en producción

Comprender los sistemas de notificaciones: lo básico

Un sistema de notificaciones es una infraestructura distribuida responsable de entregar información oportuna a los usuarios a través de múltiples canales. En esencia, resuelve un problema fundamental: ¿cómo envías de forma confiable el mensaje correcto a la persona correcta en el momento correcto a través de su canal preferido?

¿Qué es un sistema de notificaciones?

Piensa en un sistema de notificaciones como un sofisticado pipeline de mensajería. Cuando le das “me gusta” a la publicación de alguien en LinkedIn, esa acción dispara un evento. Ese evento fluye por múltiples capas de procesamiento antes de llegar como una notificación al dispositivo de esa persona. El sistema se encarga de la validación, las preferencias del usuario, la selección del canal, el formateo del mensaje, la entrega, la lógica de reintentos y el seguimiento, todo en el transcurso de milisegundos.

Los sistemas de notificaciones modernos admiten múltiples canales:

Notificaciones push entregan alertas móviles y de escritorio mediante Firebase Cloud Messaging para Android o Apple Push Notification Service para iOS. Estos mantienen conexiones persistentes con miles de millones de dispositivos, por eso las aplicaciones individuales no gestionan estas conexiones directamente: tu batería se agotaría.

Notificaciones por email manejan mensajes transaccionales como restablecimientos de contraseña y confirmaciones de pedidos a través de servicios como SendGrid o Amazon SES. Estas requieren una gestión cuidadosa de la reputación del remitente para evitar los filtros de spam.

Notificaciones por SMS envían alertas sensibles al tiempo a través de pasarelas de telecomunicaciones como Twilio. Son costosas por mensaje y enfrentan regulaciones estrictas, por lo que se reservan para comunicaciones críticas como OTPs y alertas de seguridad.

Notificaciones in-app aparecen dentro de la aplicación usando conexiones en tiempo real como WebSockets. Son las más baratas de entregar, pero requieren que el usuario tenga la app abierta.

Por qué los sistemas de notificaciones son complejos

La complejidad surge de los requisitos de escala y confiabilidad. Un sistema que maneja 100 notificaciones al día tiene desafíos completamente distintos a uno que procesa 10 millones. Considera estos escenarios del mundo real:

Durante una venta relámpago, millones de usuarios necesitan notificaciones simultáneas. Sin una arquitectura adecuada, tus colas de mensajes se desbordan, los servidores fallan y se pierden notificaciones críticas. Los sistemas de producción usan colas dedicadas con niveles de prioridad para garantizar que los mensajes transaccionales siempre se entreguen, incluso cuando las campañas de marketing están inundando el sistema.

Las preferencias de usuario añaden otra capa de complejidad. Algunos usuarios quieren notificaciones push, pero no emails. Otros activan horario silencioso de 10 PM a 8 AM. Tu sistema debe respetar estas preferencias mientras agrupa notificaciones similares para evitar abrumar a los usuarios. Cuando 50 personas le dan “me gusta” a tu publicación, no quieres 50 avisos separados; quieres una sola notificación que diga “A John y otras 49 personas les gustó tu publicación”.

Las particularidades específicas de cada canal crean pesadillas de mantenimiento. Apple restringe las notificaciones silenciosas a una vez cada 20 minutos. Si las envías con mayor frecuencia, se limitan o se bloquean por completo. Los dispositivos en modo de bajo consumo ignoran las notificaciones de prioridad normal. Los proveedores de email tienen algoritmos complejos de detección de spam que pueden poner tu dominio en listas negras si no tienes cuidado. Los mensajes SMS enfrentan regulaciones distintas en diferentes países.

La arquitectura completa: cómo encaja todo

Un sistema de notificaciones en producción consta de varios componentes interconectados. Cada uno maneja una responsabilidad específica y, juntos, crean un pipeline resiliente que puede escalar a miles de millones de mensajes. Así es como trabajan en conjunto:

Visión general de la arquitectura de alto nivel

La arquitectura sigue un patrón de pipeline con una separación clara de responsabilidades. Los eventos fluyen por el sistema en etapas, donde cada etapa maneja responsabilidades específicas y tiene características de escalado independientes.

En el punto de entrada, tus servicios de aplicación generan eventos de notificación. Cuando un usuario comenta una publicación, procesa un pago o completa una tarea, esa acción crea un evento. Estos eventos se publican en un API gateway o servicio de notificaciones que actúa como la puerta de entrada del sistema.

El servicio de notificaciones valida las solicitudes entrantes, aplica rate limiting y realiza el filtrado inicial. Verifica si el tipo de notificación está habilitado, valida la estructura del payload y se asegura de que la solicitud tenga la autenticación adecuada. Este servicio opera de forma sincrónica con la aplicación que lo invoca, pero delega inmediatamente el trabajo al procesamiento asíncrono.

Los mensajes entran en un sistema de colas distribuido como Kafka, RabbitMQ o AWS SQS. Esto desacopla la creación de notificaciones de la entrega, permitiendo que tu aplicación responda de inmediato sin esperar la entrega real. La cola proporciona garantías de durabilidad y permite el escalado horizontal de los workers de procesamiento.

Los procesadores de notificaciones extraen mensajes de las colas y aplican la lógica de negocio. Obtienen las preferencias del usuario de una base de datos, determinan qué canales usar, formatean mensajes según plantillas y aplican reglas de agrupación de notificaciones. Aquí es donde vive la inteligencia: decidir que 50 “me gusta” deben convertirse en una sola notificación agrupada en lugar de 50 individuales.

Los workers específicos de cada canal manejan la entrega real. Pools de workers separados gestionan notificaciones push, emails y SMS porque cada canal tiene características de rendimiento y modos de fallo distintos. Los workers de push pueden procesar 10.000 mensajes por segundo, mientras que los workers de SMS manejan solo cientos debido a los límites de tasa de los carriers.

Los proveedores externos de entrega completan la entrega final. FCM y APNs mantienen conexiones persistentes con miles de millones de dispositivos. Los servidores SMTP enrutan emails a través de internet. Las pasarelas SMS se integran con operadores de telecomunicaciones. Tu sistema envía solicitudes correctamente formateadas a estos servicios y maneja sus respuestas.

Una capa de seguimiento y analítica monitorea todo el pipeline. Registra intentos de entrega, captura fallos, registra interacciones del usuario como aperturas y clics, y genera métricas para paneles de monitoreo. Estos datos vuelven al sistema para mejorar las tasas de entrega y optimizar la interacción de los usuarios.

Explicación de los componentes principales

Desglosemos cada componente en detalle, entendiendo no solo qué hace sino por qué está diseñado de esa manera.

El Notification Gateway

El gateway sirve como la capa de API del sistema. Acepta solicitudes de notificación desde tus servicios de aplicación y proporciona dos modos operativos: envío de una sola notificación y envío por lotes. Por ejemplo, al procesar una campaña masiva de email, el modo batch te permite enviar miles de notificaciones en una sola llamada a la API en lugar de hacer solicitudes individuales.

Este componente maneja autenticación, autorización y validación inicial. Aplica límites de tasa de API para prevenir abusos y protege los sistemas downstream de verse desbordados. El gateway mantiene acuerdos de nivel de servicio implementando circuit breakers que evitan fallos en cascada cuando los servicios downstream no están saludables.

Consejo de producción: Implementa claves de idempotencia a nivel del gateway. Cuando un cliente reintenta una solicitud fallida, la clave de idempotencia evita que se creen notificaciones duplicadas. Esto es crítico para notificaciones transaccionales como confirmaciones de pago, donde los duplicados generan confusión en los usuarios y tickets de soporte.

Sistema de colas de mensajes

La cola proporciona la columna vertebral de la confiabilidad y la escalabilidad. Las opciones populares incluyen Apache Kafka para escenarios de alto throughput, RabbitMQ para enrutamiento flexible y AWS SQS por su simplicidad gestionada. Cada una tiene distintos compromisos en términos de garantías de orden de mensajes, características de throughput y complejidad operativa.

Las colas permiten un procesamiento asíncrono que desacopla la creación de notificaciones de la entrega. Tu aplicación puede crear una notificación y responder al usuario de inmediato. La notificación se entrega en segundo plano, potencialmente segundos o minutos después, dependiendo de la profundidad de la cola y de la capacidad de procesamiento. Esto evita que servicios externos lentos bloqueen la ruta crítica de tu aplicación.

La durabilidad de los mensajes garantiza que las notificaciones sobrevivan a fallos del sistema. Cuando un mensaje entra en la cola, se persiste en disco antes de enviar la confirmación. Incluso si todos los procesadores fallan, los mensajes permanecen en la cola para procesarse cuando los sistemas se recuperen. Esto proporciona semántica de entrega de al menos una vez: toda notificación acabará siendo intentada.

El enrutamiento basado en topics separa los distintos canales de notificación. Las notificaciones por email van a un topic de email, las push a un topic de push y las SMS a un topic de SMS. Esto permite escalado independiente y aislamiento de fallos. Si la entrega de emails es lenta, no afecta a la entrega de notificaciones push porque usan colas y pools de workers separados.

Procesador de notificaciones

El procesador contiene la lógica de negocio que transforma eventos crudos en notificaciones entregables. Lee mensajes desde la cola, obtiene las preferencias del usuario desde una base de datos, aplica reglas de notificación, formatea mensajes usando plantillas y publica notificaciones formateadas en colas específicas por canal.

El manejo de preferencias del usuario requiere un diseño cuidadoso. El procesador consulta una base de datos de preferencias para determinar la configuración de canales de cada usuario, la configuración de horario silencioso y los límites de frecuencia de notificaciones. Estos datos se almacenan en caché agresivamente porque se leen para cada notificación, pero cambian con poca frecuencia. Redis o Memcached suelen servir como la capa de caché con una implementación del patrón cache-aside.

El renderizado de plantillas convierte datos estructurados en mensajes formateados. Una plantilla de notificación podría especificar que una notificación de “me gusta” debe mostrar {{actor_name}} liked your post, con distinto formato para canales push, email e in-app. El procesador sustituye las variables de la plantilla con datos reales y genera payloads específicos por canal.

La lógica de batching evita la fatiga por notificaciones. Cuando ocurren múltiples eventos similares dentro de una ventana de tiempo, el procesador los combina en una sola notificación. Esto requiere mantener estado sobre notificaciones recientes por usuario, normalmente usando una caché con ventana temporal. La ventana de agrupación y las reglas varían según el tipo de notificación: los “me gusta” pueden agruparse agresivamente, mientras que las alertas de seguridad nunca se agrupan.

Servicios de entrega por canal

Cada canal de notificación requiere un manejo especializado debido a requisitos y restricciones específicos de la plataforma. Los servicios de canal actúan como adaptadores que traducen payloads genéricos de notificación a formatos específicos del canal y gestionan las interacciones con proveedores externos de entrega.

Los servicios de notificaciones push gestionan el registro de device tokens y la entrega mediante FCM o APNs. Los device tokens deben almacenarse y mantenerse actualizados porque pueden expirar o cambiar cuando los usuarios reinstalan aplicaciones. El servicio maneja la invalidación de tokens procesando la retroalimentación de entrega de FCM y APNs, eliminando tokens inválidos de la base de datos.

Los servicios de email se integran con proveedores SMTP como SendGrid, Mailgun o Amazon SES. Manejan la verificación del dominio remitente, mantienen la reputación de IP, gestionan rebotes y quejas, y procesan webhooks para eventos de entrega. El email tiene las consideraciones de entregabilidad más complejas porque los servidores de correo de los destinatarios toman decisiones sofisticadas de detección de spam.

Los servicios de SMS se integran con pasarelas de telecomunicaciones mientras manejan las complejidades del enrutamiento internacional. Distintos países tienen diferentes operadores, regulaciones y precios. El servicio debe seleccionar sender IDs apropiados, manejar correctamente la codificación de caracteres y gestionar costos implementando estrategias de fallback por SMS para entregas fallidas.

El recorrido del mensaje: del evento a la notificación

Entender el ciclo de vida completo de una notificación te ayuda a construir sistemas más confiables. Sigamos una notificación desde su creación hasta su entrega, examinando qué ocurre en cada etapa.

Paso 1: Generación del evento

Cuando Sarah le da “me gusta” a la publicación de Bob en una plataforma de redes sociales, el servicio de aplicación que maneja esa acción crea un evento de notificación. Este evento contiene datos estructurados: el tipo de evento (post_liked), el actor (Sarah), el usuario objetivo (Bob), el ID de la publicación y una marca de tiempo. El servicio publica este evento en el notification gateway mediante una llamada a API HTTP.

La llamada a la API incluye una clave de idempotencia para evitar notificaciones duplicadas si se reintenta la solicitud. El gateway valida el payload de la solicitud contra un esquema, autentica al servicio que llama y verifica los límites de tasa. Si todo pasa la validación, el gateway responde inmediatamente con 202 Accepted: no espera la entrega.

Paso 2: Persistencia en la cola

El gateway publica el evento validado en un topic de Kafka para el procesamiento de notificaciones. Kafka persiste el mensaje en disco a través de múltiples réplicas antes de confirmar la recepción. Esto garantiza que la notificación no se perderá incluso si todo el sistema falla en ese momento. El mensaje ahora es duradero y se procesará eventualmente.

El orden de los mensajes se conserva dentro de una partición, pero las notificaciones para diferentes usuarios pueden procesarse en paralelo. Kafka particiona los mensajes por ID de usuario, asegurando que todas las notificaciones para Bob se procesen en orden mientras las notificaciones de otros usuarios se procesan concurrentemente en otras particiones.

Paso 3: Verificación de preferencias y procesamiento

Un procesador de notificaciones consume el mensaje desde Kafka. Obtiene las preferencias de notificación de Bob desde una base de datos PostgreSQL, consultando primero la caché. Bob tiene habilitadas las notificaciones push y las alertas in-app, pero ha desactivado las notificaciones por email para los “me gusta”. El procesador respeta estas preferencias y prepara mensajes solo para los canales habilitados.

El procesador revisa notificaciones similares recientes usando Redis. Encuentra que Bob recibió otras tres notificaciones de “me gusta” en la última hora. En lugar de crear una cuarta notificación separada, actualiza la notificación agrupada existente para que diga “A Sarah y otras 3 personas les gustó tu publicación”. Esto evita la fatiga por notificaciones mientras garantiza que Bob siga informado.

A continuación ocurre el renderizado de plantillas. El procesador carga la plantilla de notificación de “me gusta” y sustituye variables: nombres de actores, vista previa del contenido de la publicación y marca de tiempo. Genera payloads separados para canales push e in-app porque tienen requisitos de formato y límites de caracteres diferentes. La notificación push tiene un límite de 178 caracteres, mientras que la in-app puede ser más larga.

Paso 4: Enrutamiento por canal

El procesador publica notificaciones formateadas en colas específicas por canal. La notificación push va al topic push_notifications, mientras que la notificación in-app va al topic in_app_notifications. Cada mensaje incluye el payload formateado, los device tokens del destinatario para push y metadatos como nivel de prioridad y configuración de time-to-live.

Los niveles de prioridad afectan el orden de procesamiento. Las notificaciones transaccionales como restablecimientos de contraseña tienen prioridad alta y pasan al frente de la cola. Las notificaciones de marketing tienen prioridad baja y se procesan durante horas de menor carga. Esto garantiza que las notificaciones críticas siempre se entreguen incluso cuando el sistema está bajo alta carga.

Paso 5: Entrega externa

Un worker de notificaciones push consume el mensaje y llama a la API de Firebase Cloud Messaging. Incluye el device token de Bob, el payload de la notificación y opciones de entrega como prioridad y time-to-live. FCM acepta la solicitud y devuelve una respuesta exitosa. El worker registra este intento de entrega en una base de datos MongoDB para analítica y depuración.

FCM mantiene una conexión persistente con el dispositivo de Bob. Cuando su teléfono está en línea y accesible, FCM entrega la notificación en milisegundos. La notificación aparece en su pantalla de bloqueo y en la bandeja de notificaciones. Si el teléfono de Bob estuviera desconectado, FCM pondría la notificación en cola y la entregaría cuando el dispositivo se reconectara, respetando la configuración de time-to-live.

Mientras tanto, el worker de notificaciones in-app almacena la notificación en una tabla PostgreSQL. La próxima vez que Bob abra la app, la aplicación consulta esta tabla y muestra nuevas notificaciones en la UI. Las notificaciones in-app no requieren servicios externos de entrega porque la aplicación las obtiene mediante pull en lugar de recibirlas por push.

Paso 6: Confirmación de entrega y analítica

El sistema rastrea el estado de entrega a lo largo de todo el pipeline. Cuando FCM confirma la entrega, el worker actualiza el estado del registro de notificación a entregado. Si Bob toca la notificación, la app móvil envía un evento de analítica registrando la interacción. Estos eventos alimentan paneles que muestran tasas de entrega, tasas de apertura y métricas de interacción.

El manejo de fallos es crítico para la confiabilidad. Si FCM devuelve un error indicando que el device token de Bob es inválido, el worker marca el token como inactivo en la base de datos. Esto evita futuros intentos de entrega desperdiciados. Si FCM no está disponible temporalmente, el worker devuelve el mensaje a la cola para reintentar con exponential backoff.

Gestión de múltiples canales de notificación

Cada canal de notificación tiene características, restricciones y buenas prácticas únicas. Entender estas diferencias es esencial para construir un sistema robusto de notificaciones multicanal.

Notificaciones push: móvil y web

Las notificaciones push requieren gestionar device tokens que identifican instalaciones específicas de la app. Cuando un usuario instala tu aplicación, esta se registra en FCM o APNs y recibe un token único. Tu backend debe almacenar este token junto con el ID del usuario y mantenerlo actualizado. Los tokens pueden expirar o cambiar cuando los usuarios reinstalan la app, por lo que tu sistema debe procesar la retroalimentación de entrega y limpiar los tokens inválidos.

Los formatos de payload específicos por plataforma añaden complejidad. Las notificaciones push de iOS usan una estructura JSON distinta a la de Android. iOS requiere claves específicas como aps, alert y badge, mientras que Android usa objetos data y notification. Tu sistema necesita lógica de formateo separada para cada plataforma, o puedes usar un formato interno normalizado y transformarlo durante la entrega.

La configuración de prioridad y time-to-live afecta el comportamiento de entrega. Las notificaciones de alta prioridad despiertan dispositivos dormidos y se entregan inmediatamente. Las de prioridad normal se entregan oportunistamente cuando el dispositivo está activo para ahorrar batería. El time-to-live determina cuánto tiempo FCM o APNs intentarán entregar si el dispositivo está desconectado. Para notificaciones sensibles al tiempo, como OTPs, usa valores TTL cortos para que expiren rápido.

Las notificaciones silenciosas permiten sincronización de datos en segundo plano sin molestar al usuario. Sin embargo, Apple las restringe a una vez cada 20 minutos por aplicación. Si las envías con más frecuencia, iOS las limita o las bloquea por completo. Esto significa que no puedes depender de las notificaciones silenciosas para actualizaciones de fondo críticas en tiempo real.

Notificaciones por email: entregabilidad y reputación

La entregabilidad del email depende en gran medida de la reputación del remitente. Proveedores como Gmail y Outlook rastrean el comportamiento de tu dominio emisor y asignan una puntuación de reputación. Si envías demasiados mensajes que los usuarios marcan como spam, tu puntuación cae. Eventualmente, los proveedores empiezan a filtrar tus emails a carpetas de spam o a bloquearlos por completo.

Protocolos de autenticación como SPF, DKIM y DMARC demuestran que estás autorizado para enviar desde tu dominio. Sin una configuración adecuada, los proveedores tratan tus emails con sospecha. Estos mecanismos basados en DNS permiten que los servidores receptores verifiquen que el servidor emisor es legítimo y no ha sido suplantado.

El manejo de rebotes y quejas mantiene la reputación. Los hard bounces indican direcciones de email inválidas que deben eliminarse de tu base de datos inmediatamente. Los soft bounces sugieren problemas temporales como buzones llenos; reinténtalos unas pocas veces antes de desistir. Las quejas ocurren cuando los usuarios marcan tu email como spam. Las tasas altas de quejas dañan la reputación rápidamente, así que monitorea esta métrica de cerca y haz visibles los enlaces para darse de baja.

El contenido importa para la detección de spam. Evita palabras detonantes de spam, mantén una buena proporción entre texto e imagen, incluye una dirección física y proporciona mecanismos claros para darse de baja. Los emails transaccionales como restablecimientos de contraseña tienen requisitos distintos a los emails de marketing: los transaccionales nunca deben incluir contenido promocional o te arriesgas a problemas de entregabilidad.

Notificaciones por SMS: costo y cumplimiento

Las notificaciones por SMS son costosas comparadas con otros canales. Los costos varían por país y operador, desde fracciones de centavo hasta varios centavos por mensaje. Esto hace que los SMS sean adecuados solo para notificaciones de alto valor donde el costo se justifica: códigos de autenticación, alertas de transacciones y notificaciones críticas del sistema.

El cumplimiento normativo varía por región. Estados Unidos requiere consentimiento explícito y una identificación clara del remitente. La UE tiene requisitos de GDPR más estrictos. Algunos países requieren registrar el sender ID ante autoridades de telecomunicaciones. Tu sistema necesita rastrear el estado de consentimiento por usuario y aplicar reglas de cumplimiento antes de enviar.

La codificación del mensaje afecta el costo. Un SMS estándar soporta 160 caracteres usando codificación GSM-7. Los mensajes Unicode para caracteres no latinos reducen la capacidad a 70 caracteres por mensaje. Los mensajes más largos se dividen en segmentos, y cada segmento se factura por separado. Un mensaje Unicode de 200 caracteres consume tres créditos SMS en lugar de uno.

Los acuses de recibo de entrega confirman que el mensaje llegó al teléfono del destinatario. Sin embargo, no garantizan que el usuario lo haya leído, solo que el operador lo entregó correctamente. Algunos operadores ni siquiera soportan acuses de entrega, por lo que no puedes depender de ellos para todos los mensajes.

Escalar a millones: desafíos de producción

Construir un sistema de notificaciones que funcione para 100 usuarios es sencillo. Escalar ese mismo sistema para manejar millones de usuarios expone desafíos que solo aparecen a gran escala. Estos son los problemas reales de producción que enfrentarás y cómo resolverlos.

Manejo de picos de tráfico

Las ventas relámpago, las noticias de última hora y los eventos virales crean picos de notificaciones que pueden ser 100 veces la carga normal. Durante el anuncio de una oferta de Black Friday, cada usuario podría recibir una notificación simultáneamente. Sin una arquitectura adecuada, tus servidores fallan y se pierden notificaciones transaccionales críticas.

Las colas de mensajes proporcionan la defensa principal contra los picos. Cuando llega un millón de notificaciones en un minuto, la cola las almacena temporalmente y permite que los workers procesen a su ritmo sostenible. La profundidad de la cola crece temporalmente, pero se vacía gradualmente a medida que los workers procesan los mensajes. Monitorea la profundidad de la cola como una métrica clave: un crecimiento rápido indica capacidad insuficiente de workers.

El auto-scaling de workers responde a la profundidad de la cola. Configura tu sistema de orquestación de contenedores (Kubernetes, ECS) para lanzar instancias adicionales de workers cuando la profundidad de la cola supere un umbral. Los workers escalan horizontalmente porque no tienen estado: cada uno procesa mensajes de forma independiente sin coordinación. Durante picos, podrías escalar de 10 workers a 100 y luego volver a reducir durante períodos tranquilos.

Las colas con prioridad garantizan que las notificaciones críticas se entreguen incluso durante picos. Crea colas separadas para notificaciones transaccionales de alta prioridad y mensajes de marketing de baja prioridad. Las colas de alta prioridad reciben pools de workers dedicados que no se ven afectados por el tráfico de campañas de marketing. Esto garantiza que los emails de restablecimiento de contraseña lleguen rápido incluso cuando estás enviando un millón de notificaciones promocionales.

Gestión de límites de tasa de servicios externos

Los servicios externos de entrega imponen límites de tasa para proteger su infraestructura. SendGrid podría limitarte a 1.000 emails por segundo. Twilio podría fijar un máximo de 50 SMS por segundo. APNs permite unas 2.000 conexiones por segundo. Si excedes estos límites, recibirás throttling o serás bloqueado temporalmente.

El rate limiting con token bucket aplica las restricciones de tu lado. Antes de llamar a una API externa, verifica si tienes tokens disponibles en tu bucket. Si no, espera hasta que el bucket se recargue. Esto evita que tus workers saturen los servicios externos y sean bloqueados. Implementa buckets separados para cada servicio externo, ya que tienen límites distintos.

El tamaño de los pools de workers debe respetar los límites de tasa. Si SendGrid permite 1.000 emails por segundo y cada worker envía 10 emails por segundo, puedes ejecutar como máximo 100 workers. Ejecutar más workers solo hace que queden inactivos esperando tokens del rate limit. Ajusta el tamaño de los pools en función de la capacidad del servicio externo, no de tu capacidad de procesamiento interna.

Usa llamadas batch a la API cuando sea posible. En lugar de llamar a FCM una vez por notificación, agrupa entre 100 y 500 notificaciones en una sola solicitud batch. Esto reduce la sobrecarga de API y te ayuda a mantenerte dentro de los límites de tasa. Sin embargo, el batching añade latencia: las notificaciones esperan hasta que se llene el lote o expire un timeout. Equilibra el tamaño del lote con el retraso de entrega aceptable.

Garantizar confiabilidad con lógica de reintentos

Los servicios externos fallan con regularidad. Los problemas de red causan timeouts. Los servicios tienen caídas. Los límites de tasa se exceden pese a tus mejores esfuerzos. Tu sistema necesita una lógica de reintentos sofisticada para manejar estos fallos transitorios sin crear notificaciones duplicadas ni perder mensajes.

El exponential backoff evita tormentas de reintentos. Después de un fallo, espera 1 segundo antes de reintentar. Si vuelve a fallar, espera 2 segundos, luego 4, 8, 16, hasta un máximo. Esto da tiempo a que los servicios que fallan se recuperen mientras garantiza que acabarás reintentando. Añade jitter aleatorizando ligeramente los tiempos de espera para evitar reintentos sincronizados de múltiples workers.

Los límites máximos de reintentos evitan bucles infinitos. Después de 5 o 10 intentos fallidos, mueve el mensaje a una dead letter queue para investigación manual. Algunos fallos son permanentes: device tokens inválidos, direcciones de email deshabilitadas, números de teléfono inexistentes. Reintentarlos eternamente desperdicia recursos sin lograr la entrega.

La idempotencia evita entregas duplicadas. Cuando una solicitud agota el tiempo de espera, no sabes si tuvo éxito o falló. El servicio externo puede haberla procesado aunque tú no hayas recibido respuesta. Incluye una clave de idempotencia única en cada solicitud para que el servicio pueda detectar e ignorar envíos duplicados.

Las dead letter queues capturan mensajes que fallan permanentemente. Contienen información valiosa de depuración: ¿por qué falló repetidamente esta notificación? El análisis de dead letters suele revelar problemas de configuración, errores en el renderizado de plantillas o problemas sistemáticos con tipos específicos de notificación. Monitorea la profundidad de la dead letter queue como una métrica clave de confiabilidad.

Rendimiento de la base de datos a escala

Cada notificación requiere acceso a la base de datos para obtener preferencias del usuario, device tokens e historial de notificaciones. Con millones de notificaciones al día, las consultas a la base de datos se convierten en un cuello de botella a menos que diseñes con cuidado.

Las read replicas distribuyen la carga de consultas. Las preferencias de usuario y los device tokens tienen muchas lecturas pero pocas escrituras. Dirige estas lecturas a bases de datos réplica dedicadas que van ligeramente por detrás de la primaria. Esto evita que el tráfico de lectura impacte el rendimiento de escritura de la base de datos primaria.

Las capas de caché reducen drásticamente los accesos a la base de datos. Las preferencias de usuario cambian rara vez: almacénalas en Redis con un TTL de 1 hora. Los device tokens cambian cuando los usuarios reinstalan aplicaciones: almacénalos con un TTL de 24 horas. Una tasa de aciertos de caché del 95% significa que sirves 19 de cada 20 solicitudes desde caché en lugar de consultar la base de datos.

El particionamiento del historial de notificaciones evita el crecimiento excesivo de tablas. Particiona por mes o trimestre para que cada partición contenga un volumen de datos manejable. Las particiones antiguas pueden archivarse en almacenamiento más barato o eliminarse por completo. Sin particionamiento, tu tabla notification_deliveries crecerá a miles de millones de filas y las consultas se volverán lentísimas.

El connection pooling evita agotar las conexiones de la base de datos. Cada worker necesita conexiones, pero crear nuevas conexiones es costoso. Usa pools de conexiones que mantengan un conjunto reutilizable de conexiones. Ajusta el tamaño de los pools en función del número de workers y de la concurrencia de consultas: si son demasiado pequeños, generan contención; si son demasiado grandes, desperdician recursos de la base de datos.

Detalles de implementación específicos de cada plataforma

Cada plataforma de notificaciones tiene particularidades y requisitos únicos. Entender estos detalles evita errores frustrantes y te permite construir una entrega más confiable.

Firebase Cloud Messaging (FCM)

FCM maneja notificaciones push de Android y también soporta iOS y web. Proporciona tanto APIs HTTP v1 como legacy, pero la API legacy está siendo retirada gradualmente. La API v1 requiere autenticación OAuth 2.0 en lugar de claves de API simples, lo que añade complejidad pero mejora la seguridad.

La mensajería por topics permite difusión eficiente a múltiples dispositivos. En lugar de enviar a tokens individuales, publicas en un topic y FCM distribuye a todos los dispositivos suscritos. Esto es perfecto para anuncios globales o notificaciones basadas en categorías. Los dispositivos se suscriben del lado del cliente, lo que da a los usuarios control sobre las categorías de notificación.

Las prioridades de los mensajes afectan el momento de entrega y el uso de batería. La prioridad alta despierta inmediatamente a los dispositivos dormidos, pero consume más batería. La prioridad normal entrega oportunistamente cuando el dispositivo ya está activo, ahorrando batería pero añadiendo latencia. Usa prioridad alta con moderación y solo para notificaciones realmente urgentes.

Los payloads de notificación y de datos sirven para propósitos distintos. Los payloads de notificación muestran automáticamente notificaciones del sistema. Los payloads de datos entregan información personalizada a tu app, que debe encargarse de la lógica de visualización. Para máxima flexibilidad, envía ambos: el sistema muestra una notificación y tu app recibe datos para actualizar su UI.

Las respuestas de error indican por qué falló la entrega. NotRegistered significa que el token es inválido y debe eliminarse. InvalidRegistration sugiere un token mal formado. MessageTooBig indica que el payload excedió el límite de 4KB. Maneja cada tipo de error adecuadamente para mantener bases de datos de tokens limpias y evitar fallos repetidos.

Apple Push Notification Service (APNs)

APNs requiere autenticación basada en certificados o autenticación basada en tokens. La autenticación por certificado usa un archivo .p12 que expira anualmente y debe renovarse. La autenticación por token usa una clave .p8 que nunca expira, por lo que es el enfoque preferido para nuevas implementaciones.

Las conexiones HTTP/2 deben mantenerse con cuidado. APNs usa HTTP/2 para toda la comunicación, permitiendo múltiples solicitudes sobre una sola conexión. Sin embargo, las conexiones inactivas se cierran después de unos 30 minutos. Tu librería cliente debería implementar connection pooling y reconexión automática para evitar solicitudes fallidas.

La selección del entorno determina qué servidor de APNs usar. Desarrollo usa api.sandbox.push.apple.com para apps distribuidas mediante Xcode. Producción usa api.push.apple.com para apps del App Store. Enviar al entorno equivocado causa errores de autenticación crípticos.

Las alertas críticas evitan el modo No molestar, pero requieren permisos especiales. Estas reproducen sonido y se muestran incluso cuando el dispositivo está silenciado, lo que las hace adecuadas para alertas críticas de seguridad. Apple requiere aprobación del App Store para el permiso de alertas críticas y lo reserva para casos de uso realmente críticos.

Los números de badge deben gestionarse del lado del servidor. iOS no incrementa automáticamente el badge count: debes rastrear el conteo por dispositivo y enviar el total actual. Cuando los usuarios abren tu app, envía una solicitud de reinicio de badge a APNs o envía nuevas notificaciones con badge: 0.

SendGrid y la entrega de email

SendGrid proporciona tanto SMTP como APIs HTTP para enviar email. La API HTTP es más rápida y ofrece más funciones, como renderizado de plantillas y programación. SMTP funciona con clientes de correo existentes, pero carece de funciones avanzadas. Para sistemas de notificaciones, usa la API HTTP para mayor control y rendimiento.

Las plantillas dinámicas separan el contenido del código. Define plantillas de email en la UI de SendGrid con sintaxis Handlebars para sustitución de variables. Tu aplicación envía los datos de la plantilla mediante la API sin contener HTML en el código. Esto permite que personas no técnicas actualicen el contenido de los emails sin despliegues de código.

Los eventos de webhook proporcionan datos de entrega e interacción. Configura webhooks para recibir eventos como delivered, opened, clicked, bounced y spam_report. Procesa estos eventos para actualizar el estado de la notificación, eliminar direcciones inválidas y calcular métricas de interacción. Usa solicitudes de webhook firmadas para verificar que los eventos provienen realmente de SendGrid.

Las listas de supresión evitan enviar a direcciones que han rebotado o se han dado de baja. SendGrid mantiene estas listas automáticamente en función de la retroalimentación de entrega. Antes de enviar, verifica si una dirección está suprimida. Intentar enviar a direcciones suprimidas desperdicia créditos y daña la reputación.

La reputación de IP afecta significativamente la entregabilidad. Las IP compartidas significan que tu reputación está influenciada por el comportamiento de otros clientes de SendGrid. Las IP dedicadas te dan control total, pero requieren volumen de envío para mantener la reputación. Para remitentes de alto volumen con buenas prácticas, las IP dedicadas mejoran la entregabilidad.

Construir tu sistema de notificaciones: ejemplos de código

Veamos ejemplos prácticos de código para implementar componentes centrales de un sistema de notificaciones. Estos ejemplos usan Python con librerías populares, pero los patrones se aplican a cualquier lenguaje.

API del Notification Gateway

El gateway proporciona una API REST para enviar notificaciones. Valida solicitudes, aplica rate limiting y publica en la cola de mensajes. Este ejemplo usa FastAPI como framework web y Kafka como message broker.

Consumidor de la cola de mensajes

El consumidor procesa mensajes desde Kafka, aplica lógica de negocio y enruta a colas específicas por canal. Maneja errores correctamente con lógica de reintentos y soporte para dead letter queue.

Worker de entrega de notificaciones push

El worker de entrega envía notificaciones push a través de FCM con manejo adecuado de errores, lógica de reintentos y gestión de tokens. Procesa mensajes en lotes para mayor eficiencia.

Errores comunes y cómo evitarlos

Después de construir sistemas de notificaciones durante años, he visto los mismos errores una y otra vez. Estos son los problemas más comunes y cómo evitarlos.

No implementar idempotencia

Error: Permitir notificaciones duplicadas cuando los sistemas reintentan solicitudes fallidas. Los problemas de red causan timeouts, pero la solicitud pudo haber tenido éxito. Reintentarlo crea duplicados que confunden y molestan a los usuarios.

Solución: Incluye una clave de idempotencia única en cada solicitud de notificación. Almacena las claves procesadas en Redis con un TTL de 24 horas. Antes de procesar un mensaje, verifica si su clave existe en la caché. Si aparece, omite el procesamiento: la notificación ya fue manejada. Esto evita duplicados incluso con reintentos ilimitados.

Ignorar las preferencias del usuario

Error: Enviar notificaciones por canales que los usuarios han desactivado. Esto ocurre cuando la verificación de preferencias sucede en la capa equivocada o se omite por completo bajo carga.

Solución: Verifica siempre las preferencias antes de enrutar a colas por canal, nunca en la capa de entrega del canal. Almacena las preferencias agresivamente en caché para evitar cuellos de botella en la base de datos. Implementa reglas de precedencia de preferencias: una exclusión global tiene prioridad sobre cualquier otra configuración. Registra las violaciones de preferencias para depuración.

Mala gestión de tokens

Error: Almacenar device tokens inválidos para siempre e intentar entregas repetidamente. Esto desperdicia recursos y daña tu reputación con los servicios de notificaciones push.

Solución: Procesa la retroalimentación de entrega de FCM y APNs para identificar tokens inválidos. Márcalos como inactivos de inmediato y exclúyelos de futuras entregas. Implementa tareas periódicas de limpieza que eliminen tokens inactivos durante más de 90 días. Actualiza los tokens cuando los usuarios reinstalen apps o cambien de dispositivo.

Entrega sincrónica que bloquea el código de la aplicación

Error: Llamar a APIs de notificaciones de forma sincrónica desde el código de la aplicación, bloqueando solicitudes orientadas al usuario mientras se espera la entrega. Un servicio de email lento puede hacer que tu aplicación web se sienta torpe.

Solución: Usa siempre colas de mensajes asíncronas. Tu aplicación publica en la cola y responde de inmediato. Los workers en segundo plano manejan la entrega real. Si la cola no está disponible, falla rápido y registra el error en lugar de bloquear solicitudes del usuario.

Monitoreo y alertas insuficientes

Error: No monitorear métricas de entrega de notificaciones hasta que los usuarios se quejan. Los fallos silenciosos hacen que los usuarios pierdan notificaciones críticas sin que nadie lo sepa.

Solución: Rastrea tasa de entrega, tasa de error, profundidad de cola y latencia de procesamiento para cada canal. Genera alertas cuando la tasa de entrega caiga por debajo del umbral o la tasa de error se dispare. Monitorea la profundidad de la dead letter queue como señal temprana de problemas sistemáticos. Implementa health checks que envíen notificaciones de prueba y verifiquen la entrega.

No planificar el fallo

Error: Asumir que los servicios externos siempre estarán disponibles. FCM, APNs, SendGrid y Twilio también tienen caídas. Tu sistema debe manejarlas con elegancia.

Solución: Implementa circuit breakers que detecten servicios fallando y dejen de enviar solicitudes temporalmente. Usa exponential backoff para los reintentos. Pon mensajes en cola durante las caídas y vacía la cola cuando los servicios se recuperen. Ten mecanismos de fallback: si falla push, usa una notificación in-app como respaldo.

Buenas prácticas en producción

Ejecutar sistemas de notificaciones en producción requiere excelencia operativa más allá de simplemente escribir código. Estas prácticas aseguran confiabilidad, capacidad de depuración y mantenibilidad.

Logging integral

Registra cada etapa del procesamiento de notificaciones con logging estructurado. Incluye ID de notificación, ID de usuario, canal, marca de tiempo y resultado en cada entrada de log. Usa correlation IDs para rastrear una notificación a través de todo el pipeline, desde la creación hasta la entrega. Esto facilita mucho la depuración cuando los usuarios reportan notificaciones faltantes.

Evita registrar datos sensibles como el contenido del mensaje, información de contacto del usuario o tokens de autenticación. Registra metadatos sobre la notificación —tipo, prioridad, canal— pero no el mensaje real. Esto protege la privacidad del usuario mientras mantiene la capacidad de depuración.

Métricas y paneles

Rastrea métricas clave para cada canal de notificación. La tasa de entrega mide qué porcentaje de notificaciones llega correctamente a los usuarios. La tasa de apertura muestra interacción para push y email. La tasa de clics indica cuán atractivas son tus notificaciones. El tiempo de respuesta rastrea la latencia de extremo a extremo desde el evento hasta la entrega.

Construye paneles que muestren estas métricas en tiempo real. Incluye líneas de tendencia para identificar degradación tempranamente. Genera alertas sobre anomalías: tasa de entrega por debajo del 95%, tasa de error por encima del 1%, profundidad de cola creciendo continuamente o latencia excediendo los SLA.

Estrategias de testing

Los unit tests verifican componentes individuales como la comprobación de preferencias, el renderizado de plantillas y la lógica de reintentos. Los integration tests validan interacciones entre componentes: ¿el procesador enruta correctamente los mensajes según las preferencias del usuario? Los end-to-end tests envían notificaciones de prueba a través de todo el sistema y verifican la entrega.

Las pruebas de carga revelan cuellos de botella antes de producción. Simula picos de tráfico para verificar que tu sistema puede manejar 10 veces la carga normal. Prueba escenarios de fallo: ¿qué ocurre cuando FCM está caído durante una hora? ¿Tu sistema se recupera correctamente cuando los servicios regresan?

Despliegues graduales y feature flags

Despliega gradualmente nuevos tipos de notificación. Comienza con el 1% de los usuarios, monitorea problemas y luego aumenta al 10%, 50% y finalmente 100%. Usa feature flags para habilitar o deshabilitar tipos de notificación sin despliegues de código. Si un nuevo tipo de notificación causa problemas, desactívalo de inmediato mediante una feature flag.

Haz pruebas A/B del contenido de notificaciones y las estrategias de entrega. Prueba diferentes plantillas de mensaje, horas de envío y combinaciones de canales para optimizar la interacción. Mide tasas de apertura y de clics para determinar qué resuena con los usuarios.

Documentación y runbooks

Documenta tu arquitectura con diagramas claros que muestren el flujo de datos. Mantén runbooks para tareas operativas comunes: cómo agregar un nuevo tipo de notificación, cómo depurar notificaciones faltantes, cómo manejar caídas de servicios externos. Incluye guías de solución de problemas con códigos de error comunes y sus soluciones.

Mantén las plantillas de notificación y la configuración en control de versiones. Esto proporciona historial de auditoría de cambios y permite rollbacks sencillos. Revisa el contenido de notificaciones con equipos de producto y legal antes del lanzamiento para asegurar cumplimiento con regulaciones y lineamientos de marca.

Cierre

Ahora ya entiendes cómo funcionan los sistemas de notificaciones a escala, desde la arquitectura básica hasta los desafíos de producción. Hemos cubierto el recorrido completo de una notificación a través de múltiples etapas de procesamiento, examinado requisitos de entrega específicos de cada plataforma y explorado soluciones a desafíos de escalado que solo aparecen con millones de notificaciones al día.

Las ideas clave a recordar son que los sistemas de notificaciones requieren una arquitectura asíncrona con colas de mensajes, cada canal de entrega tiene restricciones y buenas prácticas únicas, las preferencias del usuario y el batching de notificaciones evitan la fatiga, y el monitoreo integral revela problemas antes de que los usuarios los noten.

Ya sea que estés construyendo un sistema de notificaciones desde cero, optimizando uno existente o preparándote para entrevistas de diseño de sistemas, estos patrones arquitectónicos y prácticas operativas te serán muy útiles. La complejidad de los sistemas de notificaciones suele sorprender a los ingenieros, pero comprender los fundamentos los hace mucho más abordables.

¿Qué desafíos de notificaciones estás enfrentando en tus sistemas? ¿Te has encontrado con particularidades específicas de plataformas que te sorprendieron? Me encantaría conocer los problemas interesantes que has resuelto.

Más artículos