Post

Arquitetura de Notificações Omnichannel: Push, SMS e Email em Escala

Arquitetura de Notificações Omnichannel: Push, SMS e Email em Escala

Em sistemas modernos, notificações são o “pulso” da aplicação. O usuário quer saber o momento exato em que seu salário caiu, quando sua compra foi aprovada ou quando recebeu uma mensagem. Mas quando você tem milhões de usuários e múltiplos canais (Push, SMS, Email, WhatsApp), construir um serviço de notificação robusto e escalável é um desafio técnico fascinante.

O maior erro é acoplar a lógica de notificação diretamente no serviço de negócio. A solução é um Notification Service centralizado e desacoplado.

Acoplamento e Latência

Imagine o PaymentService chamando a API do Twilio (SMS) ou do Firebase (Push) de forma síncrona:

  1. Latência: Se o Twilio demorar 5 segundos, o seu pagamento demora 5 segundos a mais.
  2. Disponibilidade: Se o Firebase estiver fora, o seu pagamento falha?
  3. Complexidade: O seu código financeiro não deveria saber o que é um Device Token do Android.

A Solução: Arquitetura Orientada a Mensagens

O design ideal utiliza um padrão de Fan-out usando um Broker de mensagens (Kafka ou RabbitMQ).

  1. Evento: O PaymentService publica um evento PaymentApprovedEvent no Kafka.
  2. Orquestração: O NotificationService consome este evento e consulta as preferências do usuário (ex: ele quer Push? SMS?).
  3. Entrega: O sistema dispara jobs assíncronos para cada canal.

O Modelo de Dados de Notificação

1
2
3
4
5
6
public class NotificationRequest {
    private String userId;
    private NotificationTemplate template; // "PAYMENT_SUCCESS"
    private Map<String, String> parameters; // {amount: 50.00, shop: "Restaurante"}
    private List<Channel> preferredChannels; // [PUSH, SMS]
}

Estratégias de Resiliência: O Desafio dos Provedores

Provedores externos (Twilio, SendGrid, Firebase) falham o tempo todo. Seu sistema deve ser resiliente:

1. Retries com Backoff Exponencial

Se o Firebase falhou, espere 1s, depois 2s, depois 4s… antes de tentar novamente.

2. Priorização de Filas (Queuing)

Diferencie notificações críticas de promocionais.

  • Fila Alta Prioridade: OTP (One-Time Password) para login. Deve ser entregue em segundos.
  • Fila Baixa Prioridade: “Você ganhou R$ 10 de cashback”. Pode esperar minutos ou horas.

3. Rate Limiting por Usuário

Não queremos bombardear o usuário com 50 notificações seguidas. Implemente um Throttling para garantir que o usuário não receba mais de X notificações por hora em cada canal.


Funcionamento Interno e Template Engine

Em vez de escrever strings no código, utilize uma Template Engine (como Thymeleaf ou Handlebars).

1
2
String body = templateEngine.process("payment_success_sms.txt", context);
smsClient.send(phoneNumber, body);

Isso permite que o time de marketing altere o texto das mensagens sem que você precise fazer um novo deploy do código.

Curiosidade Técnica: O Id da Mensagem e o ID do Dispositivo

Muitas vezes, um usuário tem múltiplos dispositivos (um iPad e um Android). No Push, você envia para múltiplos Device Tokens, mas o usuário só quer ver uma notificação. O Notification Service deve gerenciar a lista de tokens ativos de cada userId, limpando tokens inválidos automaticamente sempre que o provedor retornar um erro de ExpiredToken.

O futuro das notificações

À medida que a Inteligência Artificial se torna onipresente, o próximo passo para os serviços de notificação é a hiper-personalização preditiva. No futuro próximo, o NotificationService não apenas entregará mensagens, mas decidirá o momento exato em que o usuário tem maior probabilidade de ler um alerta de cashback ou de ignorar um SMS promocional, transformando a comunicação em uma experiência verdadeiramente adaptativa e menos invasiva.

This post is licensed under CC BY 4.0 by the author.