“Every event is an opportunity to surprise the user — or to flood them with noise.” — #30DiasJava Logbook

🎯 Objetivo do Day 5

O quinto dia do #30DiasJava inaugurou o lado em tempo real da plataforma. A missão: construir um Notification Service capaz de tratar eventos de domínio, entregar mensagens em múltiplos canais e manter governança mesmo antes de subir para Kafka ou RabbitMQ.

🛠️ Destaques da implementação

  • Orquestração por eventos: NotificationRequestedEvent desacopla produtores dos canais (email, push, in-app). Cada listener roda de forma assíncrona com @EventListener + @Async.
  • Outbox + idempotência: registros pendentes vão para notification_outbox e só são marcados como DELIVERED quando o canal confirma. Duplicatas são bloqueadas com índices únicos.
  • WebSockets vs SSE: o serviço expõe ambos. SSE para streams leves e estáveis; WebSockets para experiências interativas. Em ambos, JWT + rate limiting em Redis.
  • Roteamento inteligente: regras de prioridade por público, janelas de silêncio e preferências por canal.
  • Observabilidade: métricas (notification_delivery_seconds, notification_retry_total), logs com traceId/recipientId e dashboards com heatmaps de erro.

💡 Lições do dia

  • Dá para começar “pequeno” com Spring Events sem fechar a porta para brokers mais robustos — basta modelar tudo como mensagens imutáveis.
  • Idempotência precisa ser tratada desde o primeiro webhook, mesmo que o tráfego ainda seja baixo.
  • Métricas e tracing são tão importantes quanto o payload: sem visibilidade, é impossível saber se os usuários estão recebendo as mensagens certas.

🔗 Recursos


Next episodeDay 6/30 — Docker Professional Stack in 7 Steps