Você provavelmente tem agora um tópico que ninguém precisa. Ele continua quente, continua gerando cobrança, continua acionando o on-call durante uma tempestade de retries — e zero valor de negócio chega ao usuário. Uma história de dev muito compartilhada este mês sobre desligar o Pub/Sub e ninguém perceber não foi um caso isolado. Em nossas auditorias nearshore para startups e scale-ups dos EUA, rotineiramente encontramos 20–40% do tráfego de eventos como peso morto: tópicos zumbis, fanouts redundantes, analytics acidentais e streams “por via das dúvidas” que ninguém assume.
Se você opera Pub/Sub, Kafka (self-managed ou Confluent), SNS/SQS ou Kinesis, você paga duas vezes: dinheiro e ruído. O dinheiro é óbvio. O ruído é pior: retries em cascata, alarmes de lag e um imposto de sistemas distribuídos a cada deploy. A correção não é uma reescrita de seis meses. É uma auditoria de 30 dias, de baixo risco, com circuit breakers e brownouts. Eis o playbook.
Por que isso importa agora
- A infraestrutura de eventos escalou mais rápido do que seu modelo de ownership. Publicar é trivial; deprecar é raro.
- Vendors recompensam fanout. Um evento para três assinaturas são 3x entregas e 3x superfícies de falha.
- Recursos movidos a IA amplificam o volume de eventos (clickstreams, traces, embeddings) e escondem desperdício em “analytics”.
- O burburinho recente na indústria (“desligamos o Pub/Sub...”) mostrou o que vemos em campo: sem explosão, grande economia.
Em um produto típico de Series B–D, com 80–200 tópicos/streams, 150–600 consumer groups e alguns produtores de alta vazão, vemos:
- 10–30% de tópicos sem consumidores efetivos (sem acks, sem efeito materializado ou consumidor offline >30 dias).
- 5–10% de fanouts de analytics que duplicam jobs batch ou CDC do data warehouse.
- 3–5% de espelhamento de notificações/eventos para múltiplos barramentos por “portabilidade” que nunca se materializou.
- 1–3% de violações de política flagrantes (PII no payload, replicação cross-region sem um DPA).
Limpar isso reduz 15–35% do gasto mensal com messaging e reduz alertas de incidente em ~25–40% porque seu sistema para de fazer retry no vazio.
A lente da auditoria: cinco perguntas por stream
Não comece por custos; comece por efeitos. Para cada tupla de tópico/stream/assinatura, responda:
- O que muda para um usuário se este stream pausar por 24 horas? Nomeie a tela, API ou SLA. Se você não conseguir, é suspeito.
- O sistema consumidor consegue se recuperar de eventos perdidos? Se a resposta for “recomputamos a partir da fonte da verdade”, é candidato a brownout.
- Esses dados estão disponíveis por um caminho mais barato? Tabela no warehouse, CDC, batch periódico, chamada direta de serviço ou cache na borda.
- Quem é o dono? Se a ownership é um handle do Slack e não um time com rotação de on-call, é dívida.
- Qual é o multiplicador de redundância? Contagem de fanouts × tentativas de entrega × replays. Multiplicadores grandes merecem rejustificativa.
Meça antes de agir: as sete métricas que expõem zumbis
Exporte isto por tópico/stream e por assinatura/consumer group para os últimos 30 dias:
- Ingest rate (mensagens/s, bytes/s) e delivery rate por consumidor.
- Liveness do consumidor (timestamp do último ack, atraso médio de ack, porcentagem do tempo consumindo).
- Lag (offsets para Kafka; idade do mais antigo sem ack para Pub/Sub/SQS).
- Contagens de retry/backoff e volume de DLQ.
- Taxa de duplicata (chaves de mensagens/eventos vistos >1 entre consumer groups dentro de N minutos).
- Churn de schema (versões/mês) e violações de schema (payloads ruins por 10k mensagens).
- Proxy de custo: entregas × bytes médios do payload (egress/saída), horas de armazenamento × partições/retenção, bytes de replicação cross-region.
Trace três distribuições: tópicos com zero acks recentes, tópicos com lag de consumidor crescendo mas sem incidentes abertos e tópicos cujo total de bytes entregues > 3× os bytes publicados. Esta última revela fanouts caros, com múltiplas assinaturas, onde ninguém explica os dois consumidores extras.
O plano de 30 dias: de baixo risco, reversível e visível
Dias 1–7: inventariar, taguear e traçar
- Faça inventário de fontes e destinos. Emita um header do produtor em toda mensagem por 30 dias: x-stream-owner, x-purpose (customer-impacting, analytics, internal cache), x-pii (none, pseudonymous, sensitive) e x-criticality (tier 0–3).
- Mapeie efeitos. Para cada consumer group, nomeie o efeito voltado ao usuário: “página de pedidos mostra status atualizado”, “e-mails de cobrança”, “dashboard interno.” Sem efeito, sem proteção.
- Habilite tracing sombra. Amostre 1–5% das mensagens e correlacione com chamadas de API, escritas em DB ou telemetria de UI a jusante. Se os streams não se correlacionam, provavelmente estão mortos.
- Defina baselines de custo. Mesmo que o preço do vendor seja opaco, compute um score relativo: deliveries × bytes × replications. Você não precisa de precisão em dólares para escolher alvos.
Dias 8–14: classificar e rascunhar a lista de cortes
- Classifique streams: Tier 0 (impacta usuário/bloqueante), Tier 1 (impacta usuário/degradação aceitável), Tier 2 (interno), Tier 3 (analytics/só backfill).
- Identifique zumbis: zero acks em 30 dias, ou consumidores com liveness < 5% e sem histórico de incidentes.
- Encontre fanouts redundantes: mesmo payload publicado em múltiplos barramentos (por ex., SNS e Kafka) “por precaução”. Escolha um. Deixe uma ponte mínima se realmente precisar de ambos.
- Detecte inflação de payload: blobs grandes (100–500 KB) em eventos usados para um único campo a jusante. Substitua por IDs e busque ao ler nos Tiers 1+.
- Candidatos a brownout: streams de Tier 1 ou 2 em que consumidores podem recomputar ou tolerar desatualização por 24h. Marque para testes com circuit-breaker.
Dias 15–21: coloque os trilhos de segurança
- Introduza circuit breakers por assinatura. Flag de feature para descartar na entrada ou na entrega da assinatura. Padrão para fail-open nos Tiers 2–3 (descartar mensagens), fail-closed no Tier 0.
- Adicione seguro de replay. Espelhe eventos brutos para um object storage barato (por ex., GCS/Amazon S3) por 7–14 dias com um log JSONL compactado ou Parquet. Se um corte quebrar algo, reidrate.
- Publique avisos de deprecação dentro do próprio stream (uma mensagem de controle a cada N minutos) e nas suas comunicações internas. Se ninguém gritar, é um sinal.
- Snapshots de observabilidade. Um dashboard por candidato: ingest/deliveries/lag/retries, timestamp do último efeito e um grande nome do responsável.
Dias 22–30: brownouts, cortes e consolidação
- Execute brownouts: queda de 1 hora em 5–10% do tráfego no horário comercial para Tiers 2–3. Depois, 4 horas a 100% para Tier 3 fora do pico. Observe tickets de suporte, SLOs e dashboards.
- Delete ou desabilite zumbis (sem acks, sem efeito). Sem meias-medidas. Documente a deprecação com data de término e contato.
- Consolide fanouts. Direcione consumidores apenas de analytics por um único barramento e faça batch para o warehouse. Mate fanouts diretos para três sinks de analytics.
- Encolha a retenção nos caminhos quentes com forte fonte da verdade de apoio. Se você puder reprocessar a partir do DB ou do object storage, não precisa de 7 dias de backlog no Kafka.
- Dimensione corretamente as partições. Se 80% das partições estão quase ociosas, reduza pela metade. Para Pub/Sub e SQS, reduza o paralelismo quando ele infla custo de requisições sem ganho de latência.
Como são as economias (faixas realistas)
A precificação de messaging é um labirinto. Você não precisa de dólares exatos para decidir. Use estas contas de guardanapo para ajustar expectativas:
- Volume de entregas é a maior alavanca. Se você tem 200M de eventos/mês e média de 2,5 assinaturas, você processa 500M de entregas. Matar uma assinatura redundante em 30% dos tópicos pode cortar 15–25% do total de entregas imediatamente.
- Tamanho do payload importa. Reduzir o payload médio de 20 KB para 3–5 KB (IDs, não blobs) reduz tráfego de saída (egress) e armazenamento em ~70–85% para esses streams. Se só 30% do seu tráfego é inchado, você ainda economiza ~20% do egress geral.
- Retenção é gasto furtivo. Cortar a retenção do Kafka de 7 dias para 48 horas nos caminhos quentes (enquanto espelha para object storage) pode aparar 40–60% do storage nos brokers. Para Kafka gerenciado, isso reduz a fatura diretamente. Para self-hosted, são menos discos e menos páginas “Kafka sem espaço”.
- Partições e conexões impulsionam a sobrecarga operacional. Reduzir contagem de partições em 30–50% em tópicos subutilizados remove tempestades de rebalancing e corta CPU em dois dígitos.
Em empresas que gastam de alguns milhares a dezenas de milhares por mês com messaging (Confluent, Pub/Sub, SNS/SQS, Kinesis), vemos 15–35% de redução de custos em 30–60 dias com esta auditoria, além de uma queda mensurável no volume de incidentes. O ganho operacional muitas vezes supera a diferença na fatura.
Governança para o desperdício não voltar a crescer
Desligar coisas é a parte fácil. Mantê-las desligadas exige três hábitos.
1) Coloque a responsabilidade in-band
- Todos os produtores devem definir x-stream-owner para um alias de time que esteja de on-call. Políticas do broker rejeitam mensagens sem isso.
- Todos os consumidores devem registrar uma x-criticality tag e uma classificação de dados. Sem tag, sem assinatura.
- Tópicos sem time responsável expiram automaticamente em 90 dias, a menos que sejam renovados.
2) Coloque brownouts no CI/CD
- Todo novo stream embarca com um circuito de circuit-breaker e um teste de brownout de 1 hora em staging que valida que os SLOs voltados ao usuário ficam verdes ou degradam dentro dos limites definidos.
- Bloqueie deploys para streams que falharem no teste de brownout sem uma isenção Tier 0 aprovada.
3) Pare de fingir que todos os eventos são em tempo real
- Defina duas pistas: operacional (latência sub-1s, Tiers 0–1) e analítica (latência em minutos, Tiers 2–3). Faça com que novos analytics padronizem em batch ou micro-batch via ingestão do seu warehouse (por ex., CDC + modelos incrementais).
- Audite trimestralmente: qualquer consumidor analítico no seu barramento operacional deve ganhar uma exceção ou migrar.
Trade-offs arquiteturais que você deve reconhecer
- Event-sourcing vs. event-driven. Se você usa o log como fonte da verdade, não reduza retenção ou partições às cegas. Sua história de replay é sua história de uptime.
- Acoplamento entre serviços. Substituir eventos gordos por IDs pode reintroduzir lookups síncronos. Tudo bem para Tiers 1–3; para caminhos de Tier 0 com SLOs de latência estritos, mantenha estado mínimo no evento (hashes, version IDs) e faça cache com inteligência.
- Latência de analytics. Mover analytics para fora do barramento quente pode deslocar dashboards de “tempo real” para “quase tempo real” (segundos a minutos). Pergunte quais decisões realmente precisam de frescor sub-segundo. A maioria não precisa.
- Segurança e compliance. Espelhar para object storage para replay é mais barato, mas você deve aplicar os mesmos controles de acesso, criptografia e políticas de retenção — ou melhores. O time de compliance deve aprovar.
Falhas comuns (e como evitá-las)
- Consumidores silenciosos. Um serviço lê mas descarta no chão. Detecte via “beacons de efeito”: se um consumidor escreve em um DB/tabela, emita um heartbeat periódico com o último offset aplicado. Sem beacon = sem efeito.
- Duplicação sombra. Dois times publicam o mesmo evento com schemas ligeiramente diferentes. Corrija com um registro, contratos e ownership clara. Publicadores duplicados são um cheiro; una ou depreque.
- Cegueira de brownout. Você rodou um brownout durante um período calmo e declarou vitória. Agende pelo menos um teste no pico para Tiers 1–2 antes de matar.
- Otimizar o barramento errado. Alguns times se obsessam com Kafka enquanto 60% do custo está em fanouts do Pub/Sub ou entregas HTTP do SNS. Meça todos os barramentos; otimize primeiro o maior ofensor.
O que automatizar a seguir
- Scorecards de tópicos. Job noturno marca tópicos com um score de dívida (sem owner, baixa liveness, alto fanout, muitos retries) e abre tickets automaticamente após limiares.
- Guardas de orçamento. Orçamentos por barramento que disparam brownouts automáticos para streams de Tier 3 quando o gasto L7 excede a previsão em 20%+.
- Linting de schema. Gancho de CI que rejeita payloads acima de um limite de tamanho ou contendo campos não permitidos (por ex., PII bruta) a menos que haja uma dispensa.
- Bots de consolidação. Para consumidores de analytics duplicados, proponha um único egress para o warehouse com um diff de contrato de dados e uma janela de migração.
Onde o nearshore se encaixa
Se seu time está no limite, este é um engajamento arrumado e delimitado para um pod nearshore: 4–6 semanas, 2–3 engenheiros embedados, um líder SRE e um liaison de produto para validar impacto no usuário. Espere 6–8 horas de sobreposição com fusos dos EUA a partir do Brazil, demos semanais, relatórios de brownout e uma “lista de cortes” concreta com planos de rollback. É o tipo de trabalho que se paga no primeiro trimestre — porque tópicos zumbis não discutem com planilhas.
O benefício silencioso: menos alertas e deploys mais rápidos
Ao remover desperdício, você reduz tempestades de rebalancing, cadeias de backpressure e casos de borda de idempotência que só aparecem às 2h da manhã. Menos consumidores significam menos lugares para vazar PII, menos políticas de IAM para gerenciar e um raio de explosão menor para os inevitáveis maus deploys. Você não está só economizando dinheiro; está comprando clareza.
Principais pontos
- Você provavelmente está operando 20–40% de tráfego de eventos zumbi ou redundante. Meça efeitos primeiro, não dólares.
- Em 30 dias, com circuit breakers e brownouts, você pode apagar ou consolidar um terço dos seus tópicos com segurança.
- Concentre-se em entregas, tamanho do payload, retenção e partições — esses são seus maiores alavancas.
- Impeça o desperdício de voltar a crescer com tags de ownership in-band, brownouts no CI e governança de duas pistas (operacional vs. analítica).
- O ganho operacional (menos incidentes, ownership mais claro) frequentemente supera a redução da fatura.
Autor: Diogo Hudson Dias