Skip to content

Rate Limits de Mensageria — Wasender API

Constante centralizada: supabase/functions/_shared/messaging-rate-limits.ts (backend) e src/lib/messaging-rate-limits.ts (frontend).


Plano Atual: Basic ($6/mês)

RecursoLimite
Send Message256 requests/minuto por sessão
Sessões WhatsApp1
Mensagens/mêsIlimitadas (sem custo por mensagem)
Cap diárioSem limite (apenas Trial tem 50/dia)
Account Protection ModeSe ativado: 1 req/5s (12/min) — sobrescreve limite do plano

Tabela Comparativa de Planos

PlanoPreço/mêsSend Message/minSessõesCap diário
TrialGrátis256150 msgs
Basic$62561Ilimitado
Pro$122563Ilimitado
Plus$182565Ilimitado
Business$3025610Ilimitado

Nota: O rate limit de 256/min é por sessão e aplica-se a todos os planos pagos. A diferença entre planos é o número de sessões simultâneas.


Proteções Implementadas

1. Cooldown no Frontend (Reenviar OTP)

  • Valor: 60 segundos entre reenvios
  • Onde: src/components/login-unified.tsx — botão "Reenviar código"
  • Constante: MESSAGING_RATE_LIMITS.cooldownReenvioOtpSegundos
  • Comportamento: Após envio de OTP, botão mostra countdown "Reenviar em Xs" e fica desabilitado
  • Natureza: Apenas UX — a proteção real é no backend

2. Rate Limit no Backend (OTP) — PROTEÇÃO REAL

  • Por usuário: Máximo 3 OTPs em 15 minutos (query em login_otps por usuario_id)
  • Por IP: Máximo 10 OTPs em 1 hora (query em login_otps por ip_origem)
  • Onde: Edge Function send-otp
  • Resposta: HTTP 429 quando excedido
  • Proteção contra: CURL, bots, requisições em massa — qualquer client

3. Adapter Centralizado

  • Todo envio passa por enviarMensagemComLog() em _shared/wasender-whatsapp.ts
  • Ponto único de envio via WhatsApp (Wasender)
  • Ponto único para aplicar throttle futuro

Guia para Envio em Massa (Futuro)

Conta correta

text
Limite do plano: 256 requests/minuto por sessão
Plano Basic: 1 sessão

Configuração segura:
  1 worker sequencial × delay de 275ms ≈ 3.6 msgs/segundo ≈ 218 msgs/minuto
  218/256 = 85% do limite → margem de 15%

Nota: O erro anterior era usar MÚLTIPLOS workers (3×250ms = 720/min = BAN).
      Com 1 worker, o delay de 275ms é seguro.

Implementação

typescript
import { MESSAGING_RATE_LIMITS } from "../_shared/messaging-rate-limits.ts";

// Fila sequencial — NUNCA paralela
for (const destinatario of lista) {
  await enviarMensagemComLog(destinatario, mensagem);
  await delay(MESSAGING_RATE_LIMITS.delayEntreEnviosMs); // 275ms
}

Por que NÃO usar concorrência

A documentação do Wasender afirma que alta concorrência é a causa #1 de ban do WhatsApp.

Com 1 sessão (plano Basic), múltiplos workers disparam requests simultâneos contra o mesmo limite:

text
❌ 3 workers × 250ms delay = 12 msgs/s = 720 msgs/min (BAN CERTO)
❌ Promise.all sem controle = rajada instantânea (BAN CERTO)
✅ 1 worker × 275ms delay = 3.6 msgs/s ≈ 218 msgs/min (seguro, margem 15%)

Concorrência só faria sentido com múltiplas sessões (planos Pro+), e mesmo assim, 1 worker por sessão.

Recomendações

  1. Fila sequencial — 1 worker, await delay(275) entre cada mensagem
  2. Checar sessão — Validar status via check_whatsapp_session antes de iniciar bulk
  3. Circuit breaker — Se 3 falhas consecutivas, pausar fila por 30s e alertar via ntfy
  4. Monitorar — Logar cada envio, acompanhar taxa de sucesso

Anti-padrões

❌ Errado✅ Correto
Promise.all(msgs.map(enviar)) — rajada sem controleFila sequencial com await delay(275)
Múltiplos workers na mesma sessão1 worker sequencial por sessão
Enviar 1000 msgs sem checar sessãoValidar sessão antes, pausar se desconectada
Ignorar erros e continuar enviandoCircuit breaker após 3 falhas consecutivas

Glossário

TermoSignificado
ThrottleLimitar a velocidade de envio (delay fixo entre mensagens). Correto e necessário.
ConcorrênciaMúltiplos workers enviando em paralelo. Anti-padrão para 1 sessão — multiplica requests contra o mesmo limite.
Circuit breakerPadrão que pausa envios após N falhas consecutivas para evitar cascata de erros.

Checklist: Mudança de Plano

markdown
□ Atualizar `MESSAGING_RATE_LIMITS.plano` e `custoMensal`
□ Atualizar `sessoesDisponiveis` se mudou
□ NÃO aumentar `maxConcorrencia` além de 1 por sessão
□ Verificar se `accountProtectionMode` está habilitado no dashboard Wasender
□ Atualizar tabela comparativa neste documento
□ Testar bulk sending com novos valores

Histórico

DataMudança
2026-03-30Documento criado. Constante centralizada + cooldown 60s no reenviar OTP.
2026-03-30Correção: concorrência 3→1, delay 250ms→1000ms. Conta anterior estava errada (720/min vs 256 limite).