/projects/dietbox-notifications

← Todos os projetos

Dietbox Notifications

Tudo o que o produto envia para fora, movido para um serviço próprio.

Head de Tecnologia · 2023–2024

.NET 6C#CQRSSQL ServerWhatsApp Business APIAzure DevOps
WebsitePrivado

Visão geral

Este serviço existe por causa de um número numa fatura: a conta de mensageria oficial do WhatsApp em maio de 2023. A resposta não foi um limite de taxa colado no produto existente, mas um serviço pequeno e próprio que assumiu o envio — e, por ser dono de cada envio, conseguia prestar contas deles.

O que eu fiz

Escrevi o documento de design, o domínio e o serviço: dezenove dos vinte commits, da primeira estimativa ao serviço em produção.

  • O próprio documento de planejamento de capacidade — as estimativas de volume, taxa de consultas e armazenamento que o serviço foi construído para atender.
  • O modelo de domínio, e o registro de cada notificação enviada que fica no centro dele.
  • Os dois controllers e seus comandos e queries — enviar uma notificação e ler de volta o que foi enviado.
  • Os pacotes transversais atrás das camadas: a integração com o provedor do WhatsApp e a injeção de dependência.

O problema

A conta oficial da API do WhatsApp Business chegou em maio de 2023, e nada no produto sabia dizer com o que aquilo estava sendo gasto — os envios saíam de vários lugares e não eram registrados em nenhum. O lugar óbvio para resolver isso era o próprio produto principal, mas ele já era complexo demais para ser estendido com segurança. A alternativa foi tirar o envio de lá por completo: um serviço que é dono do canal, registra cada mensagem e pode mudar sem colocar em risco o produto que atende.

Em números

Esses quatro números vêm do próprio documento de design do serviço, escrito antes de existir uma linha dele — um plano de capacidade, não uma medição de produção feita depois.

~51 milmensagens por mêso volume que estava sendo pago
~30 milconsultas por dia0,3 QPS em média
5QPS de pico previsto
~1,4 GBarmazenamento em dez anos214 bytes por notificação

Arquitetura

Um serviço chamador chega ao endpoint de notificação, que entrega a mensagem ao provedor do WhatsApp e registra o resultado de qualquer forma — então toda mensagem que o produto envia deixa uma linha para trás.

  1. Calling serviceOutro serviço da plataforma solicita uma notificação em nome de um profissional.
  2. Notify endpointO controller de notificação recebe a requisição e dispara o comando de envio.
  3. Send commandO envio é tratado como um comando nomeado, então o pedido e o registro dele são a mesma história.
  4. ProviderA integração com o WhatsApp envia a mensagem pela API oficial, atrás do pacote transversal do provedor.
  5. Sent recordO resultado — enviado ou recusado — é gravado no registro que toda notificação deixa.

Uma notificação, do pedido ao registro

  1. RequestedUm serviço chamador pede o envio de uma notificação a um profissional.
  2. AcceptedO pedido é validado e vira um comando de envio para aquela profissional.
  3. DispatchedA mensagem segue para o provedor do WhatsApp, atrás do pacote transversal que o encapsula.
  4. RecordedQualquer resultado é gravado no registro de notificações enviadas, então "essa mensagem saiu mesmo?" tem resposta sem depender de perguntar ao provedor.

O que faz

  • Um controller de notificação e o comando que envia a notificação de uma profissional.
  • Um controller de nutricionista e queries sobre o histórico de notificações enviadas dessa profissional.
  • Um registro de cada notificação enviada, que é o que torna o gasto explicável depois do fato.
  • Um serviço em camadas com pacotes transversais para o provedor do WhatsApp e injeção de dependência, mantidos separados do domínio que sustentam.

Decisões de engenharia

  • Um serviço separado especificamente para ser ignorável

    O objetivo declarado era zero impacto no produto principal. Isolar o serviço de notificações significou que ele podia ser desligado, reimplantado ou reescrito sem derrubar o produto junto — o oposto de colar um limitador num código que já era complexo demais para tocar com segurança.

  • A medição foi construída e nunca foi ligada

    Existe no domínio um limite por profissional e um log de quem o alterou, construídos para que o custo pudesse um dia ser cobrado de quem o gerou. Essa parte nunca foi usada — o que o serviço fez todo dia foi enviar e registrar. A decisão continua no card porque o limite ainda está no código, e deixá-la de fora descreveria um serviço que nunca foi construído.

  • Capacidade planejada antes da primeira linha

    O volume mensal, a taxa de consultas e o espaço ocupado em dez anos foram estimados no documento de design antes de o serviço ser construído, e é por isso que a decisão de armazenamento — quanto espaço isso jamais precisaria — foi uma pergunta entediante e já respondida, não uma surpresa.

  • Um provedor primeiro, a interface para mais

    O WhatsApp foi a conta que originou tudo isso, então é o único provedor que envia hoje — mas email, SMS e push foram o formato que o domínio e a API foram desenhados para aceitar depois, sem que o registro de envio precisasse mudar.