Operação · · 12 min de leitura · Time Catcher

Como rodar múltiplos números de WhatsApp
em produção sem cair

Rodar 1 número de WhatsApp em automação é razoavelmente simples, qualquer biblioteca open source resolve. Rodar 10 números simultâneos sem ban é uma operação completamente diferente, com requisitos técnicos e operacionais que ninguém te conta antes de você começar a perder dinheiro com banimentos.

Esse artigo é o guia que a gente gostaria de ter tido quando começou. Vai cobrir: por que multi-número é diferente de single-número, os 5 problemas que aparecem em escala, as decisões de arquitetura que evitam a maioria deles, e o setup operacional que mantém tudo rodando.

Por que multi-número é fundamentalmente diferente

O instinto inicial de quem vai escalar é: "se 1 número funciona, 10 funcionam, só rodo 10 cópias do meu bot." Esse raciocínio leva pro pior cenário possível. As 10 cópias acabam compartilhando IP, compartilhando fingerprint, compartilhando padrões de envio. A Meta detecta o cluster em horas e bane tudo de uma vez.

Multi-número correto exige que cada instância seja completamente isolada da outra, do ponto de vista da rede e do dispositivo. Cada número deve aparentar ser um aparelho distinto, em um IP distinto, em uma cidade distinta, com padrões de envio distintos. É como manter 10 personas separadas, qualquer "vazamento" entre elas (mesmo IP, mesmo timestamp de envio, mesma mensagem) cria correlação detectável.

A boa notícia: depois de você acertar a arquitetura, escalar pra 50 ou 100 números é só repetir o mesmo modelo. A má notícia: arquitetura ruim no começo significa refazer tudo depois do primeiro ban em massa.

Os 5 problemas que aparecem em escala

Problema 1, Pool de IPs compartilhado

Bibliotecas tradicionais e provedores baratos usam pool de IPs compartilhado: sua biblioteca/provedor tem 100 IPs disponíveis, e cada conexão pega um disponível na hora. Isso funciona pra 1 número (você sai de 1 IP por vez). Pra 10 números simultâneos, você está saindo de 10 IPs do mesmo pool, e o resto dos clientes desse provedor também. A Meta vê dezenas de contas saindo dos mesmos endpoints e marca o pool inteiro como suspeito.

Solução: IP residencial estática (ISP) dedicada por instância. Cada número precisa ter sua própria IP, exclusiva enquanto a instância existir, nenhum outro cliente usa em paralelo. Custa cerca de R$ 20-30/mês por IP em provedores como Bright Data, IPRoyal ou Smartproxy. Pra 10 números, são R$ 200-300/mês de proxy, divisão saudável dentro do custo total da operação.

Nota técnica: "ISP proxy" é o termo correto pra esse tipo de IP. Tecnicamente é um IP alocado por um provedor de internet brasileiro real (Vivo, Claro, etc.) e classificado como residencial nas listas de reputação que a Meta consulta, embora a máquina que serve esteja em datacenter do provedor de proxy. É melhor que IP de datacenter (flag instantâneo) e que pool compartilhado, mas é inferior a 4G móvel real. Pra grande maioria das operações, ISP dedicada é o sweet-spot.

Problema 2, Fingerprint device idêntico

Por padrão, bibliotecas de WhatsApp Web reportam o mesmo fingerprint pra todas as instâncias: mesma versão de Chrome, mesma versão de Linux, mesmo timezone, mesmo locale. Pra Meta, ver 10 contas reportando exatamente "Chrome 120 / Linux x86_64 / GMT-3 / pt-BR" é assinatura clara de operação automatizada.

Solução: rotacionar fingerprint por instância. Cada uma deve reportar device diferente, algumas iPhone, algumas Android, algumas Web Desktop, com versões variadas. Idealmente o fingerprint também deve ser geograficamente coerente: se o número é de SP (DDD 11), o device deve reportar timezone GMT-3 e MCC 724 (Brasil). Se o número é de Salvador (DDD 71), idem. Tem que parecer que cada número está em um aparelho real, em uma cidade real.

Problema 3, Padrões de envio sincronizados

Se sua aplicação dispara mensagens em todas as 10 instâncias ao mesmo tempo (ex: cron às 9h da manhã, ou trigger imediato após evento), a Meta vê 10 contas com timestamps idênticos. Isso é correlação clara, humanos não enviam exatamente no mesmo segundo.

Solução: jitter randomizado entre instâncias. Quando você quer disparar 10 mensagens (uma por número), espalhe ao longo de 5-15 minutos. Use queue assíncrono (Asynq, BullMQ, Sidekiq, RabbitMQ, qualquer um) e adicione delay aleatório por instância. Cada número opera em ritmo independente.

Problema 4, Sessão SQLite corrompida

Bibliotecas como whatsmeow e Baileys salvam sessão WhatsApp em SQLite. Quando você roda 10 instâncias na mesma máquina, é tentador colocar todas no mesmo arquivo SQLite ou no mesmo diretório. Resultado: lock contention, escritas concorrentes corrompendo o banco, perda de session keys, número precisando re-parear via QR.

Solução: arquivo SQLite separado por instância, em diretório próprio: sessions/{instance_id}.db. Cada cliente WhatsApp abre o seu próprio. Sem lock cross-instance, sem corrupção. Catcher já estrutura assim por padrão; em outras libs, configure manualmente.

Problema 5, Eventos perdidos sob carga

WhatsApp Web emite eventos constantemente: mensagem recebida, status de entrega, presença, mudança de grupo. Com 10 instâncias rodando, você tem 10 streams de eventos chegando simultaneamente. Se sua arquitetura processa eventos no thread principal de forma síncrona, sob spike (10 mensagens chegando ao mesmo tempo) você vai perder eventos por timeout ou OOM.

Solução: separe a recepção de eventos do processamento. Cada instância publica seu evento em uma queue/pub-sub (Redis Pub/Sub, RabbitMQ, Kafka). Workers separados consomem. Se um pico ocorrer, a queue absorve, e você processa no ritmo que conseguir. Catcher faz isso via Redis Pub/Sub + worker pool, vide nossa arquitetura.

Catcher Pro · Pricing escalonado

Quanto mais instâncias, menor o preço por instância.

5+ instâncias: R$ 77/cada. 20+: R$ 57/cada. 100+: R$ 47/cada. Cada uma com IP residencial estática (ISP) dedicada.

Ver calculadora de preços →

Decisões de arquitetura que evitam dor

A maioria dos problemas acima vem de uma única raiz: tratar multi-instância como "single-instância repetida". Quem desenha desde o início pra escalar evita 80% das pegadinhas. Aqui está o modelo que a gente roda em produção.

Separação API-process vs Worker-process

Resista à tentação de rodar tudo num único processo. A API HTTP (que recebe requests do seu cliente) deve ser um processo distinto do Worker (que mantém as sessões WhatsApp ativas). Por quê? Porque você vai precisar reiniciar a API com frequência (deploys, hotfix, etc), e cada restart da API não pode derrubar suas sessões WhatsApp, elas demoram pra subir de novo, podem disparar warmup novamente, podem gerar reconnect storms.

Modelo correto:

  • API process: recebe HTTP, valida auth, enfileira tarefas, lê DB, expõe SSE/WS pra clientes. Pode reiniciar a qualquer momento sem impacto.
  • Worker process: mantém todos os clientes WhatsApp ativos, processa eventos, processa filas de envio. Reinicia raramente (uma vez por deploy de mudança em libs do WhatsApp).

Catcher faz exatamente isso desde 2026: dois binários separados (biazap-api + biazap-worker), comunicando via Redis Pub/Sub e Asynq. Resultado: deploys da API são instantâneos e não causam reconnect.

Throttle por instância (não global)

Limites de envio devem ser por instância, não no nível da aplicação. Se você quer que cada instância respeite uma curva de warmup (ex: 20→50→100→200→500/dia conforme a idade), o throttle precisa ser stateful por instância. Implemente via Redis com keys tipo throttle:{instance_id}:hour e throttle:{instance_id}:day, com TTL automático. A Catcher complementa esse padrão de mercado com termômetro de contato, limite por reciprocidade do destinatário, não só por idade da instância.

Pause inteligente em sinais de risco

WhatsApp Web emite eventos quando algo está estranho: StreamReplaced (outro device tomou a sessão), ConnectFailure (falha persistente), LoggedOut (Meta deslogou o número). Se sua arquitetura ignora esses eventos e fica tentando reconectar agressivamente, você acelera o ban, a Meta percebe a tentativa repetida e classifica como bot insistente.

Modelo correto: quarantine a instância em sinais de risco. Pause envios, marque desired_state=DISCONNECTED, alerte o operador humano. Reconnect só acontece após intervenção manual (operador clicou "Reconectar" e reescaneou o QR se necessário). Catcher chama isso de "Natural Mode" e isso reduziu o ban-rate em ~40% comparado ao auto-reconnect padrão.

Setup operacional do dia-a-dia

Monitoramento por instância, não só agregado

Métricas globais ("9.000 mensagens enviadas hoje") escondem problemas. O que importa é métrica por instância: quantas mensagens cada uma mandou, qual taxa de entrega, qual ban-rate, quantos minutos cada uma ficou offline. Catcher expõe tudo isso no Console em tempo real, mas você consegue replicar em qualquer stack:

  • Counter Prometheus whatsapp_messages_total{instance_id, status}, incrementa em cada envio com status (sent, delivered, read, failed).
  • Gauge whatsapp_instance_health{instance_id}, 1 quando online, 0 quando offline.
  • Histogram whatsapp_send_duration_seconds{instance_id}, latência por instância.

Com isso você consegue alertar quando uma instância específica desvia do baseline (ex: ban rate dela passa de 1% enquanto a média do pool é 0.3%).

Heartbeat e detecção de instância "morta"

WhatsApp Web pode parar de receber/enviar sem deslogar oficialmente, você fica num zumbi. A instância parece online, mas nada chega nem sai. Sem detecção, você descobre só quando o cliente reclama "minhas mensagens não estão indo".

Heartbeat simples: a cada 60s, marque last_activity_at da instância no DB toda vez que qualquer evento entra/sai. Cron a cada 5 minutos verifica: se last_activity_at tem mais de X horas (X depende do seu tipo de tráfego, pode ser 6h pra negócio comercial), a instância está com sintoma de zumbi. Alerte.

Catcher tem um sistema de tiers (healthy / stale / degraded / offline / critical_offline) que abstrai isso e dispara webhook + email automaticamente.

Fila resiliente com retry exponencial

Em algum momento, sua aplicação cliente vai estar offline quando uma instância tiver mensagem pra entregar. Ou o webhook que recebe os eventos vai estar fora. Sem fila resiliente, eventos somem.

Asynq (Go) ou BullMQ (Node) ou Sidekiq (Ruby), escolha um framework de fila com retry exponencial nativo. Configure: 5 tentativas, com delays 5s/15s/30s/1m/2m. Se ainda falhar, vai pra DLQ (dead letter queue) pra inspeção manual. Catcher usa Asynq com retry de até 30 tentativas e janela total de ~22h pra absorver outages do consumidor.

Logs estruturados, não printf

Com 10 instâncias rodando, você não consegue debugar olhando log textual. Use logs estruturados (JSON) com campos consistentes: {instance_id, event_type, timestamp, ...}. Catcher usa zerolog com schema padronizado. Conseguir filtrar todos os eventos de uma instância específica via grep/jq é diferença entre 30 segundos e 2 horas de debug.

Quando você está pronto pra escalar

Antes de adicionar a instância número 11, garanta que estes itens estão funcionando pra todas as 10 atuais:

  • Cada uma tem IP residencial estática (ISP) dedicada (exclusiva enquanto a instância existir).
  • Cada uma tem fingerprint device coerente com DDD do número.
  • Warmup phased rodou completo (30 dias) sem pular bracket.
  • Throttle por instância está respeitando os limites.
  • Pause em sinais de risco está funcionando (StreamReplaced, ConnectFailure).
  • Você tem dashboard com métrica por instância.
  • Você tem alerta automático em ban-rate > 1% por instância.
  • Você tem fila resiliente com DLQ pra eventos.
  • Você tem post-mortem documentado de pelo menos 1 incidente real (porque vai acontecer).

Se algum desses estiver fragil, adicionar mais instância vai amplificar o problema, não resolver.

Onde a Catcher se encaixa

Tudo o que descrevemos acima, IP ISP dedicada por instância, TLS fingerprint sticky de navegador real, throttle por instância, termômetro de contato, quarantine em sinais de risco, anti-fingerprinting de mídia, monitoramento granular, fila resiliente, logs estruturados, é a base operacional da Catcher. A gente não vende isso como "feature avançada"; é o default. Você cria uma instância no Console e tudo isso vem ligado por padrão.

Se você está construindo do zero, copie o modelo. Se você está pensando "não quero gastar 6 meses de engenharia construindo isso", a Catcher resolve por R$ 47-97 por instância, com desconto progressivo em volume. Ver pricing.

Pronto pra escalar pra 5, 10 ou 50 instâncias?

Catcher Pro · A partir de R$ 47/instância em volume

Trial 7 dias com cartão. Cada instância com IP residencial estática (ISP) dedicada, TLS fingerprint sticky de navegador real, termômetro de contato, anti-fingerprinting de mídia, monitoramento granular.