04 - Comparação entre Brokers
video: https://youtu.be/... no frontmatter da nota.Comparação entre Brokers
Escolher o broker de mensagens é uma decisão de arquitetura com efeito de longa duração, porque consumidores, pipelines e contratos de evento crescem sobre a infraestrutura escolhida. Kafka, RabbitMQ e o par AWS SQS e SNS representam três modelos distintos: log de eventos particionado, fila tradicional com roteamento flexível e serviços gerenciados de fila e fanout. A comparação correta não busca o melhor absoluto, e sim o encaixe entre garantias do modelo e requisitos do caso de uso: volume, ordenação, retenção, roteamento, custo de operação e tamanho do time. Esta seção consolida os critérios, a tabela comparativa e os cenários de escolha por caso de uso, com os trade-offs que aparecem só depois do primeiro incidente.
Critérios de comparação
Modelo de entrega é o primeiro critério. Fila entrega cada mensagem a um consumidor e a remove; log retém os eventos e cada grupo de consumo avança por offset, permitindo múltiplas leituras independentes e replay; publicação-assinatura entrega cópias a todos os assinantes. Confundir esses modelos é a origem da maior parte das escolhas erradas.
Ordenação, garantia de entrega e retenção vêm em sequência. Ordenação por entidade exige partição por chave ou grupo de mensagens; at-least-once exige idempotência do consumidor em todos os modelos; retenção decide se reprocessamento é possível e por quanto tempo. Roteamento determina onde o despacho por conteúdo acontece: na topologia do broker, como nos exchanges do RabbitMQ e nos filtros do SNS, ou no código do produtor e do consumidor.
O último critério, e o mais negligenciado, é o custo de operação: quem conserta o broker às 3h da manhã, quem dimensiona, quem aplica patch. Broker auto-hospedado dá controle e cobra operação; serviço gerenciado elimina operação e cobra por uso com limites de serviço.
Cada dimensão carrega trade-off que só aparece em produção. Ordenação por chave cria partições quentes quando a chave é mal distribuída; retenção longa cobra armazenamento e disciplina de idempotência no replay; roteamento rico no broker concentra inteligência em topologia que exige gestão; entrega empurrada reduz latência e transfere o controle de taxa para o receptor. O desenho é escolher quais desses trade-offs o domínio aguenta melhor.
O tamanho do time também é critério técnico: plataforma operada por três engenheiros não deve começar por cluster Kafka auto-hospedado em produção, independentemente do requisito de volume, porque o custo de operação domina a conta antes do throughput aparecer.
Latência por mensagem fecha a lista. Fila tradicional entrega cada item com latência de milissegundos e sem lote obrigatório; log particionado atinge sua performance com batching do produtor, o que adiciona alguns milissegundos de janela; fila gerenciada tem latência comparável à tradicional, com variação típica de serviço compartilhado. Aplicações sensíveis a latência percebida pelo usuário precisam medir o caminho completo, incluindo o tempo de fila, e não apenas o throughput nominal do broker.
Tabela comparativa
| Critério | Kafka | RabbitMQ | SQS | SNS |
|---|---|---|---|---|
| Modelo | Log particionado com offsets | Fila AMQP com exchanges | Fila gerenciada | Fanout gerenciado |
| Entrega | At-least-once, exatamente-once com transações | At-least-once com ack manual | At-least-once, dedup em FIFO | At-least-once por assinante |
| Ordenação | Dentro da partição por chave | Só na fila de consumidor único | FIFO dentro do grupo de mensagens | Não garantida em standard |
| Throughput típico | Muito alto, dezenas de milhares por broker | Alto, escala por cluster | Praticamente ilimitado em standard | Alto, com cotas por região |
| Retenção | Por tempo ou tamanho, replay integral | Até o ack, TTL configurável | Até 14 dias | Sem retenção, entrega empurrada |
| Roteamento | Pela escolha de tópico e chave | Rico: direct, fanout, topic, headers | Nenhum: uma fila por destino | Filtros de política por assinatura |
| Replay | Nativo por offset, janela da retenção | Só em stream queues | Não nativo, exige cópia própria | Sem replay |
| Operação | Cluster auto-hospedado complexo | Cluster moderado, ferramental maduro | Nula | Nula |
| Custo em baixo volume | Alto, cluster mínimo oneroso | Moderado | Baixo, paga por uso | Baixo, paga por uso |
| Caso ideal | Stream de eventos em escala e CDC | Fila de tarefas e roteamento flexível | Fila serverless simples | Fanout para N destinos |
A leitura da tabela precisa considerar o contexto de adoção: em uma conta AWS madura, o custo operacional nulo de SQS e SNS muda o resultado da comparação para cargas médias; em plataforma on-premises com time dedicado de infraestrutura, Kafka e RabbitMQ competem por requisitos diferentes.
Duas dimensões da tabela merecem atenção dobrada. Retenção e replay é a fronteira entre os modelos: no Kafka ela é recurso nativo, no RabbitMQ existe apenas em stream queues e no SQS exige cópia manual, e é justamente essa fronteira que separa requisito de stream de requisito de fila. Operação é a fronteira econômica: o mesmo volume que torna Kafka auto-hospedado caro em time pequeno torna SQS caro em volume constante altíssimo, porque o custo por operação escala linearmente.
Nuvem gerenciada versus auto-hospedado
Os serviços gerenciados de mensageria deslocam o esforço de operar para o esforço de configurar bem: políticas de DLQ, filtros, cotas e alarmes substituem cluster, patch, backup e recuperação. Em times pequenos, esse deslocamento é a diferença entre entregar produto e virar equipe de infraestrutura.
O auto-hospedado devolve controle em troca de trabalho: tuning de disco e rede, upgrades com rebalanceamento, recuperação de desastre testada e monitoramento profundo por broker. Plataformas com volume constante alto, requisitos de residência de dados ou custo por operação proibitivo justificam o custo; o resto tende ao gerenciado.
A decisão muda com a régua do tempo. No primeiro ano, gerenciado quase sempre vence por custo total; em plataforma consolidada com volume alto, o custo variável do gerenciado pode superar o fixo do auto-hospedado, e a migração passa a ser análise financeira real, não modismo. Auditoria de custo por operação de mensagem evita surpresas nos dois sentidos.
Cenários de escolha por caso de uso
Fila de tarefas em segundo plano, como envio de e-mail, geração de documento e processamento de mídia: SQS na AWS, por simplicidade e elasticidade; RabbitMQ fora da nuvem, por madurez de fila de trabalho. Kafka é excesso, porque nenhuma tarefa precisa de replay e o custo de cluster não se paga.
Stream de eventos de negócio com múltiplos consumidores e necessidade de reprocessamento: Kafka é o default técnico. CDC de banco de dados, analytics em tempo real, integração de domínios com ordem por chave e reconstrução de estado derivado são os casos em que o modelo de log se justifica integralmente.
Fanout de um evento para vários destinos com consumo desacoplado: SNS para múltiplas filas SQS é o padrão gerenciado da AWS, com filtros por assinatura; RabbitMQ com exchange fanout cumpre o mesmo papel fora da nuvem; Kafka atende quando os destinos já são grupos de consumo no mesmo cluster.
Integração com sistema legado lento: RabbitMQ ou SQS com taxa de consumo controlada amortizam o destino; o broker vira fronteira de tolerância. Nenhum caso desse pede Kafka, e a escolha da fila tradicional reduz o custo de operar o híbrido.
Pico espinhoso com aceitação de atraso: qualquer fila resolve, e a escolha segue o contexto de nuvem e o time. O requisito real é backlog configurável e alarme de idade, que os três modelos têm, e a diferença está em quem gerencia o amortecedor.
Auditoria e histórico de eventos por exigência regulatória: o log retido do Kafka atende nativamente, com retenção longa e replay para reconstrução; fila tradicional descarta após ack e não serve como fonte de verdade de histórico. Quando o regulador pede recomposição de estado em data passada, o modelo de log deixa de ser preferência e vira requisito.
Telemetria de dispositivos e IoT com milhões de produtores e baixa por dispositivo: Kafka com produtores em lote e compressão é o desenho típico, porque o custo marginal por evento precisa ser mínimo. O contraste com fila de tarefas é nítido, e tentar servir os dois perfis com a mesma infraestrutura costuma fracassar em um deles.
Orquestração de sagas de longa duração: passos de processo distribuído com compensação seguem melhor filas por passo, com DLQ e correlação explícita, porque cada etapa é uma tarefa isolada com prazo próprio; o log serve ao histórico de eventos da saga, e a escolha separa o mecanismo de execução do mecanismo de auditoria.
Erros de encaixe: sintoma e correção
| Sintoma em produção | Escolha errada | Correção típica |
|---|---|---|
| Precisa reprocessar dados, mas fila descartou | Fila para requisito de replay | Migrar evento para log com retenção |
| Produtor com código de despacho para 6 filas | Fanout manual sem broker de distribuição | Tópico SNS ou exchange fanout |
| Partição quente limitando throughput | Chave de baixa cardinalidade no Kafka | Revisar chave, saltar com sufixo quando ordem permite |
| Consumidor do Kafka travando o pipeline | Grupo único para propósitos distintos | Separar grupos de consumo por domínio |
| Custo de cluster alto com uso baixo | Kafka por modismo | Migrar tarefas para SQS e manter Kafka onde faz sentido |
| Mensagens fora de ordem na fila | Standard onde ordem importa | FIFO com MessageGroupId ou fila por entidade |
Cada sintoma da tabela tem a mesma origem: o requisito existia, e o modelo escolhido não o expressa. Corrigir no desenho é barato antes dos contratos de evento se espalharem; corrigir depois significa migração com coexistência, idempotência reforçada e janela de publicação dupla. Revisar o encaixe a cada novo requisito de negócio é manutenção de arquitetura, não retrabalho.
# Pseudocódigo de decisão: roteiro de escolha em produção
if requisito.replay or requisito.varios_grupos_independentes:
escolher Kafka # log com retenção e offsets
elif contexto == "AWS" and requisito.roteamento_simples:
if requisito.multiplos_destinos:
escolher SNS + SQS # fanout gerenciado com filtros
else:
escolher SQS # fila serverless, custo por uso
elif requisito.roteamento_rico or requisito.fila_de_tarefas:
escolher RabbitMQ # exchanges e ack fino
else:
escolher SQS # default simples, escalonável depois
# Em qualquer ramo: consumidor idempotente, DLQ e alarme de backlog
# são obrigatórios, independente do broker escolhido.
A validação da decisão precisa de dados próprios, não de benchmark genérico. O piloto recomendado testa o pico real do domínio com payload real, mede latência por mensagem e por lote, provoca falha de consumidor e mede tempo de recuperação, e estima custo por milhão de mensagens no volume projetado. Cada uma dessas medições tende a reordenar a tabela comparativa de quem a faz.
A decisão também deve registrar o custo de saída. Condição para escolher qualquer broker é saber como sair dele: contrato de evento independente de extensão proprietária, schema versionado fora do broker e consumidores com idempotência que toleram publicação dupla durante migração. Plataforma sem rota de saída transforma decisão técnica em refém permanente do fornecedor.
Combinações comuns em produção
Plataformas maduras raramente têm um broker só. O padrão frequente é Kafka como barramento central de eventos de negócio, SQS para tarefas pontuais de aplicação e SNS para fanout de notificações; cada ferramenta no papel em que o modelo é o mais barato para o requisito. O custo dessa combinação é a integração entre os mundos, geralmente resolvida com conectores ou com pontes de consumidor para produtor. A regra que protege o desenho é um caminho por tipo de dado: evento de domínio segue pelo log, tarefa segue pela fila, e nada troca de caminho sem decisão registrada.
A combinação inversa, tudo em um único broker, simplifica operação no início e vira gargalo de desenho depois: filas de tarefa no Kafka desperdiçam o modelo de log, e streams no RabbitMQ brigam contra o modelo de fila. A regra prática é permitir mais de um broker por propósito declarado, com documentação de qual papel cada um cumpre, e evitar a terceira ferramenta sem requisito novo real.
A governança dessa pluralidade é o que a sustenta: registro de tópicos e filas com propósito, dono, SLA e política de retenção; convenção de nomes; e processo de criação que obriga a declaração do papel. Sem governança, a combinação de brokers vira zoológico, e a comparação que este arquivo propõe vira debate de opinião em cada incidente.
Migração entre brokers acontece e precisa de estratégia de coexistência: publicar em paralelo nos dois, migrar consumidores por domínio, validar lag e desligar o caminho antigo. Ferramentas de ponte entre Kafka e RabbitMQ existem, mas o plano de migração é arquitetura, não ferramenta.
Um caso de combinação frequente em plataformas híbridas é o modelo de nuvem mista: Kafka gerenciado na nuvem para o barramento central, SQS para integração serverless de borda e RabbitMQ no datacenter para o legado que ainda não migrou. O desenho exige cuidado com a fronteira, porque atravessar ela em cada mensagem cria dependência de rede entre mundos com SLA diferentes; eventos que precisam atravessar são candidatos a sincronização assíncrona com tolerância a atraso.
Erros comuns na decisão
- Escolher por familiaridade do time sem mapear garantias: a fila que o time conhece, usada fora do modelo certo, gera retrabalho maior que o aprendizado de uma ferramenta adequada.
- Subestimar o custo de operação do auto-hospedado: cluster Kafka com três brokers, monitoramento, upgrades e rebalanceamentos é função de time dedicado; sem time, o gerenciado vence o cálculo.
- Superdimensionar com Kafka para cargas de fila simples: o tópico de tarefas com 3 partições e 10 mensagens por segundo paga o cluster inteiro por nada; a economia de SQS nesse caso é de ordem de grandeza.
- Ignorar limites do gerenciado: cotas de região, tamanho de mensagem e throughput de FIFO precisam constar do desenho, porque a solução de contorno muda arquitetura, não configuração.
- Acoplar todos os consumidores ao mesmo broker sem política: falta de documentação de propósito por tópico ou fila cria massa crítica de dívida onde qualquer mudança vira incidente.
- Trocar de broker no meio do domínio sem coexistência: corte direto entre modelos diferentes perde eventos na janela da migração; publicação dupla e migração por consumidor são o caminho seguro.
- Comparar apenas throughput: latência por mensagem, roteamento, custo operacional e curva de aprendizado mudam o resultado real mais que o número de pico do benchmark.
- Esquecer a observabilidade no plano: qualquer que seja o broker, sem lag, idade de fila e alarme de DLQ, a decisão certa vira operação às cegas em produção.
- Decidir sem teste com carga real do domínio: benchmark genérico não representa o payload, a distribuição de chaves e o padrão de pico do negócio; piloto com métrica própria é parte da decisão.
- Tratar o broker como detalhe de implementação: contrato de evento, política de retenção e estratégia de idempotência são decisões arquiteturais que sobrevivem ao broker; tratá-las como acaso da ferramenta limita qualquer troca futura.
- Ignorar o custo de egresso e de operação cruzada em arquiteturas híbridas: mensagem que atravessa fronteira de rede paga transferência e latência em cada salto, e o desenho que ignora isso surpreende na fatura do segundo mês.
- Deixar a política de retenção implícita: fila que expira em 4 dias e log que retém 30 dias respondem perguntas de reprocesso diferentes; a janela precisa ser decisão documentada por fluxo, não configuração herdada.