Kafka vs RabbitMQ: a verdade nua sobre escalabilidade em microserviços

Kafka vs RabbitMQ: a verdade nua sobre escalabilidade em microserviços

Onde a Arquitetura Começa a Rachar

O caos começa sempre igual: microserviços crescendo, mais eventos circulando, instâncias subindo no Kubernetes… e a fila vira gargalo. Não é falta de CPU. Não é Docker mal configurado. É escolha errada de ferramenta.

Vejo isso direto em equipes que tentam usar RabbitMQ como se fosse Kafka e vice-versa. Um é message broker transacional. O outro é event log distribuído. Forçar o encaixe errado vira over-engineering e gera mais incêndio do que solução.

Kafka para Volume, RabbitMQ para Controle: a Regra Pragmática

Sem rodeios:

  • Kafka: throughput absurdo, histórico de eventos, reprocessamento natural, escalabilidade horizontal verdadeira.
  • RabbitMQ: roteamento poderoso, entrega garantida, ack manual, backpressure real, sem a complexidade absurda do ecossistema Kafka.

O erro clássico: usar Kafka para workloads de baixa taxa mas alta necessidade de precisão e orquestração fina. Ou usar Rabbit para processar 1 milhão de eventos por minuto. Aí vira sofrimento.

Implementação de Senior: Configurando Consumidores de Forma Correta

Exemplo direto do campo: um consumidor resiliente e escalável usando Kafka (com backpressure controlado) e outro com RabbitMQ usando ack manual para evitar perda de mensagens.

Exemplo Kafka (Node.js + KafkaJS)

import { Kafka } from "kafkajs";

const kafka = new Kafka({ brokers: ["kafka1:9092"] });
const consumer = kafka.consumer({ groupId: "pedido-processamento" });

await consumer.connect();
await consumer.subscribe({ topic: "pedidos.criados", fromBeginning: false });

await consumer.run({
  eachMessage: async ({ message }) => {
    const payload = JSON.parse(message.value.toString());

    try {
      processPedido(payload);
    } catch (err) {
      console.error("Erro ao processar. Enviando para DLQ...", err);
      await kafka.producer()
        .send({ topic: "pedidos.dlq", messages: [{ value: message.value }] });
    }
  },
});

Exemplo RabbitMQ (Node.js + amqplib)

import amqp from "amqplib";

const conn = await amqp.connect("amqp://localhost");
const channel = await conn.createChannel();

await channel.assertQueue("pagamentos");
channel.prefetch(10); // backpressure real

channel.consume("pagamentos", async (msg) => {
  try {
    const payload = JSON.parse(msg.content.toString());
    await processarPagamento(payload);
    channel.ack(msg); // controle fino
  } catch (err) {
    console.error("Falha. Rejeitando mensagem.");
    channel.nack(msg, false, false); // manda para DLQ
  }
});

A Fatura Chega: O Custo de Cada Escolha

KAFKA

  • Você ganha escala quase infinita…
  • …mas paga com infra pesada: ZooKeeper (ou KRaft), storage abundante e tunning avançado.
  • Excelente para eventos imutáveis, péssimo para workflows sensíveis.

RABBITMQ

  • Controle granular de entrega, simplicidade operacional.
  • Mas sharding é limitado, e ele sofre com throughput gigantesco.
  • Se tentar empurrar 500k msgs/s, você vai queimar a mão.

Direto das Trincheiras

  • Se precisa reprocessar eventos facilmente, nem pense: escolha Kafka.
  • Se o negócio exige orquestração e idempotência precisa, RabbitMQ é mais seguro.
  • Não suba Kafka para workloads pequenos — isso é over-engineering clássico de hype.

Fontes

Arquitetura de Software, Arquitetura de Soluções e System Design,
Blog | gaGO.io

Obrigado por acompanhar essa reflexão até o fim!

Espero que esses pontos ajudem você a tomar decisões mais lúcidas no seu próximo projeto. Não deixe de conferir outros artigos aqui no blog, onde descascamos outros hypes da nossa área.

Valeu e até a próxima! 😉

Leave a Comment

O seu endereço de e-mail não será publicado. Campos obrigatórios são marcados com *