---
title: "Desafios de escalar sistemas Java em tempo real com design orientado a eventos"
author: "Ignácio Afonso"
date: "2026-07-02 06:30:00-03"
category: "Tecnologia & Desenvolvimento"
url: "http://desbugados.scale.press/portal/desbugados/post/2026/07/02/desafios-de-escalar-sistemas-java-em-tempo-real-com-design-orientado-a-eventos/md"
---

## Resumo
- Plataforma processa 80 mil chamadas por hora e 5 milhões de transações diárias com Java e Kafka
- Três gerações de state management: Global State Stores, cache local via replay e Redis com 60% menos tempo de boot
- Consistência eventual em sinalização de chamadas equivale a falha funcional
- Boot-storms e limite de partições do Kafka criam teto rígido de escalabilidade
- Padrão first-write-wins no Redis zera latência de deduplicação gRPC
- Chamada REST síncrona bloqueante pode gerar 30 minutos de consumer lag
- Kafka Streams com RocksDB gera spikes de latência por compactação

---

Imagine uma plataforma de contact center na nuvem que precisa atender mais de 80 mil chamadas concluídas na hora de maior pico (BHCC), gerenciando 10 mil agentes e processando mais de cinco milhões de transações diárias. Essa foi a realidade enfrentada por uma equipe que construiu o sistema em Java com Apache Kafka, e o resultado revelou trade-offs que só aparecem quando o volume de produção bate na porta.

## A evolução silenciosa das três gerações de gerenciamento de estado

A primeira geração confiava inteiramente nos **Kafka Global State Stores**, que sincronizavam estado entre clusters, mas introduziam latência de sincronização que se tornava visível em operações de sinalização de chamadas. Quando o sistema cresceu para dois clusters AKS e um switch de voz no GCP, ficou claro que essa abordagem não sustentava os requisitos de sub-segundo. A segunda geração tentou resolver o problema com cache local em memória via replay de eventos do Kafka, porém o replay gerava atrasos de cinco minutos na inicialização e causava mismatches que deixavam cartões de trabalho travados por mais de 24 horas.

A terceira geração trouxe o **Redis** como cache compartilhado com thread de recuperação em background, alcançando melhora de **60 por cento** no tempo de inicialização. Essa transição não foi simples substituição, mas uma lição sobre como cada padrão de armazenamento carrega seu próprio conjunto de falhas silenciosas que só se manifestam em escala real.

## Por que consistência eventual vira falha em sistemas de tempo real

Em arquiteturas orientadas a eventos, a consistência eventual costuma ser vendida como vantagem, mas no caminho de sinalização de chamadas ela equivale funcionalmente a uma falha completa. Um atraso de alguns milissegundos pode fazer com que dois agentes atendam a mesma chamada ou que o cliente fique sem resposta por tempo demais. O artigo do InfoQ mostra que, nesse contexto específico, não há margem para o “eventualmente” porque o usuário final percebe a inconsistência como indisponibilidade.

Além disso, o padrão first-write-wins no Redis reduziu a latência mínima de deduplicação via fan-out gRPC de **200 milissegundos por hop** para praticamente zero. Essa mudança simples eliminou gargalos que antes se acumulavam em cada salto da arquitetura, demonstrando que nem sempre a solução mais “event-driven” é a mais eficiente quando o relógio está correndo contra o tempo real.

## Os boot-storms e o limite rígido das partições do Kafka

Outro ponto crítico surgiu durante a inicialização das JVMs: o replay de eventos do Kafka gerava boot-storms que desabilitavam o HPA do Kubernetes. O sistema simplesmente não conseguia subir rápido o suficiente para acompanhar picos de demanda. O limite de partições do Kafka também criou um teto rígido de escalabilidade que nenhuma configuração de cluster conseguia romper sem custos extras de latência na deduplicação cross-cluster.

Uma única chamada REST síncrona bloqueante dentro de um consumer do Kafka podia cascatear para mais de **30 minutos de lag** no consumidor, derrubando o provisionamento em massa para os 10 mil agentes. Esses números não são teóricos; eles vieram direto da operação em produção e mostram como uma decisão aparentemente inofensiva de arquitetura pode se transformar em horas de indisponibilidade.

## Lições para quem precisa decidir entre Kafka Streams, RocksDB e alternativas

O uso de **Kafka Streams com RocksDB** introduziu spikes de latência causados por compactação que tornavam a solução inviável para requisitos de sub-segundo. A equipe precisou abandonar essa combinação e buscar alternativas que priorizassem previsibilidade sobre throughput puro. O artigo ressalta que event-driven não é atalho nem vitória gratuita; ele traz novas formas de complexidade e modos de falha que só se revelam quando o sistema já está rodando em escala.

Para quem lida com sistemas legados ou está planejando modernizações, a história serve como alerta de que padrões que funcionam em bancos ou microservices genéricos podem falhar miseravelmente em domínios de tempo real como contact centers ou sinalização de voz.

## Caixa de ferramentas: próximos passos práticos

Comece auditando se seu fluxo de sinalização ou transações críticas tolera consistência eventual; se a resposta for não, priorize caches compartilhados como Redis com padrões first-write-wins. Meça o tempo real de inicialização com replay de eventos antes de escalar e teste o impacto de uma única chamada síncrona bloqueante em seus consumers. Avalie também se o limite de partições do Kafka já está próximo do teto e considere alternativas leves como o Tansu para casos de menor complexidade. Por fim, documente cada geração de estado que sua equipe já implementou para que a próxima migração não repita os mesmos cinco minutos de delay ou os 24 horas de cartões travados.