Análise Detalhada: Fluxo de Envio de Mensagens - Pilot Status
Este documento apresenta uma análise profunda do ciclo de vida de uma mensagem no sistema Pilot Status, desde a requisição na API até a entrega no WhatsApp do destinatário. O objetivo é mapear as regras, os mecanismos de resiliência, os pontos de falha e propor melhorias para alcançar a máxima garantia de entrega.
1. O Fluxo de Envio (Caminho Feliz)
O fluxo de uma mensagem passa por quatro grandes estágios:
- Entrada e Validação (API REST): O cliente faz um
POST /v1/messages/send. - Persistência e Enfileiramento: A mensagem é salva no banco de dados com status
QUEUEDe despachada para o BullMQ (apoiado por Redis). - Processamento (Worker): Um worker consome a fila, aplica variáveis de template, simula o comportamento humano ("digitando...") e faz a chamada HTTP para a Evolution API.
- Confirmação Assíncrona (Webhooks): A Evolution API dispara webhooks de volta para o Pilot Status informando
SERVER_ACK(recebido pelo servidor do WhatsApp) eDELIVERY_ACK(entregue ao celular do cliente).
2. Regras e Validações Aplicadas
Antes de uma mensagem ser sequer enfileirada, ela passa por um funil estrito de validações no endpoint da API:
- Autenticação e Ambiente:
- TEST: Permite envios apenas para o número cadastrado no perfil do desenvolvedor.
- LIVE: Exige que o projeto tenha a flag
productionApprovedverdadeira.
- Regras de Instância: Mensagens de Marketing exigem o uso de uma instância própria conectada pelo cliente. O sistema decide dinamicamente se usa a instância padrão (Pilot Status) ou a do cliente.
- Opt-in Transacional: Validado pelo
WhatsAppTransactionalOptInService. A única exceção é o envio de OTP (One Time Password) através do número oficial do Pilot Status. - Rate Limiting: Previne abusos na API, bloqueando picos anômalos de requisições.
- Time-to-Live (TTL /
deliverUntil): Se o cliente não definir, o sistema impõe limites baseados na categoria da mensagem:- OTP: Expira em 2 minutos.
- UTILITY: Expira em 1 hora.
- MARKETING: Expira em 4 horas.
3. Sistemas Atuais para Garantir o Envio
O sistema já possui uma arquitetura moderna focada em resiliência:
- Desacoplamento com Filas (BullMQ): A API não aguarda o envio para o WhatsApp. Ela apenas enfileira, garantindo respostas rápidas (baixa latência) e tolerância a picos.
- Política de Retentativas (Retries): O worker está configurado para tentar enviar a mensagem até 10 vezes, com um intervalo fixo de 30 segundos entre as falhas.
- Preservação de Tentativas (Smart Wait): Se o worker detecta que a instância do WhatsApp está desconectada (
connectingouclosed), ele não queima as retentativas. A mensagem volta paraQUEUEDsilenciosamente. - Message Reconciler (Cron/Worker): Um processo de varredura roda em background procurando mensagens presas no estado
QUEUED. Ele é responsável por reenfileirar mensagens que por algum motivo foram "esquecidas" ou marcá-las comoFAILEDse o tempo dedeliverUntilfoi ultrapassado. - Distributed Locks: O uso de travas no Redis evita que dois workers processem a mesma mensagem simultaneamente (evitando envios duplicados).
4. Condições de Falha (Quando a mensagem realmente não chega)
Uma mensagem só é marcada como FAILED (desistência total) nas seguintes situações:
- Falha Crítica (Erro 404): A Evolution API retorna que a instância solicitada não existe ou foi excluída. O sistema desiste imediatamente.
- Estouro de TTL (Timeout): O tempo limite definido no
deliverUntilé atingido (ex: WhatsApp do cliente ficou offline por mais de 2 minutos para um OTP). O Reconciler a marca como falha. - Exaustão de Retentativas: A Evolution API retorna erros temporários (ex: 500 Internal Server Error, indisponibilidade de rede) 10 vezes consecutivas (durante os 5 minutos de janela dos retries).
- Rejeição Síncrona (API): Falha no Opt-in, Rate Limit excedido ou ambiente de Teste tentando enviar para números não autorizados (neste caso, nem entra na fila).
5. Gargalos e Pontos de Falha Identificados (Vulnerabilidades)
Apesar de resiliente, a arquitetura atual possui pontos sensíveis que podem causar perda ou atraso de mensagens:
- Dependência Estrita do Redis (Single Point of Failure): Se o Redis cair, o BullMQ para. Pior: a API
POST /messages/sendfalhará ao tentar enfileirar a mensagem, retornando erro 500 para o cliente. - Intervalo de Retry Fixo (Thundering Herd): O intervalo de 30 segundos fixo para retries pode ser perigoso. Se a Evolution API cair e voltar, todas as mensagens represadas tentarão ser enviadas quase ao mesmo tempo a cada 30 segundos, podendo derrubar a Evolution API novamente.
- Perda de Webhooks: O status de "Entregue" depende exclusivamente dos webhooks da Evolution API. Se a API do Pilot Status estiver reiniciando (deploy) no exato momento em que o webhook chegar, a mensagem ficará com status "fantasmas" (
QUEUEDouSENT) para sempre, mesmo tendo chegado ao celular. - Gargalo de Fila Única: Se um cliente disparar 100.000 mensagens de Marketing, elas podem entupir o BullMQ, atrasando o envio de mensagens críticas de OTP de outros clientes. Atualmente existe a prioridade
urgent, mas filas compartilhadas ainda geram contenção.
6. Sugestões de Melhoria (Rumo à Resiliência Máxima)
Para garantir que o sistema tente entregar a mensagem ao máximo, independente de falhas de infraestrutura, recomendo as seguintes evoluções:
A. Padrão Transactional Outbox (Fim da dependência crítica do Redis)
Em vez de a API salvar no banco e tentar escrever no BullMQ na mesma requisição, a API deve apenas salvar no banco de dados (Postgres) em uma transação. Um processo separado (relé) lê as mensagens novas do Postgres e as empurra para o Redis.
- Vantagem: Se o Redis cair, a API continua aceitando mensagens (elas ficam salvas no Postgres). Quando o Redis voltar, a fila é preenchida automaticamente. Nenhuma requisição de cliente é perdida.
B. Exponential Backoff com Jitter
Alterar a política de retentativas de (10 tentativas fixas de 30s) para um recuo exponencial (ex: 5s, 15s, 45s, 2m, 5m...) adicionando um Jitter (aleatoriedade de alguns segundos).
- Vantagem: Evita ataques de DDoS acidentais na própria Evolution API quando ela se recupera de uma instabilidade.
C. Fallback de Instâncias (Roteamento Inteligente)
Se um cliente possui múltiplas instâncias conectadas (ex: suporte1, suporte2) e a instância primária desconectar, o sistema poderia tentar re-rotear a mensagem por uma instância de fallback ativa, ao invés de apenas aguardar o deliverUntil expirar.
D. Sincronização Ativa de Status (Anti-Perda de Webhooks)
O Message Reconciler deve ser aprimorado para identificar mensagens que estão no estado SENT (Enviadas para a Evolution) há mais de X minutos sem receber o webhook de DELIVERY_ACK. Nessas situações, o Reconciler faria um polling (GET ativo) na Evolution API para checar o status real e atualizar o banco.
E. Circuit Breaker na Integração com Evolution API
Implementar um Circuit Breaker no Worker. Se a Evolution API começar a retornar muitos erros 5xx seguidos, o circuito "abre" e o Worker pausa o processamento da fila BullMQ por alguns minutos.
- Vantagem: Evita gastar tentativas de retry das mensagens atoa enquanto a Evolution API está sabidamente fora do ar.
F. Dead Letter Queue (DLQ)
Mensagens que esgotam as tentativas ou falham por erro 404 devem ser movidas para uma tabela/fila de DLQ (Dead Letter Queue). Isso permite que a equipe de operações ou o próprio cliente (via Dashboard) revise o motivo da falha e clique em um botão "Forçar Reenvio" se o problema subjacente (como número de destino incorreto) tiver sido corrigido.
G. Separação Física de Filas (Lane Isolation)
Criar filas BullMQ separadas por categoria: queue:otp, queue:utility, queue:marketing. Workers independentes (ou com pesos diferentes) garantem que picos de envio de marketing nunca afetem a latência de mensagens OTP críticas.