Escalabilidade: O Engano da Resiliência em Microserviços com Kafka

Quando Kafka Vira Bengala Arquitetural

O erro clássico: achar que Kafka é cura universal para escalabilidade. **Muita gente coloca Kafka onde só precisava de um simples “retry” assíncrono**. Resultado? Over-engineering e mais uma stack que ninguém no time sabe operar.

O hype de que Kafka = resiliência cria a falsa sensação de que microserviços ficam “intocáveis”. Só que resiliência não nasce do broker — nasce do design. Se o serviço é podre, Kafka só empacota essa podridão em eventos bonitos.

Kafka Resolve? Resolve. Mas Só se o Problema For Dele.

A solução pragmática: use Kafka quando você precisa de throughput alto, eventos imutáveis, reprocessamento e pipelines de dados. Não para RPC glorificado ou como substituto de comunicação entre microserviços que só precisam responder rápido.

Quer resiliência real? Circuit breaker, idempotência e design orientado ao domínio. Kafka entra quando o domínio pede streaming, não quando o time quer parecer “cloud native”.

Implementação de Sênior: Processamento Idempotente com Kafka

Vamos ao que importa: código que evita tragédias. Consumidor Kafka com idempotência real usando chave de negócio + store simples.

using Confluent.Kafka;
using Dapper;
using Npgsql;

var config = new ConsumerConfig {
    GroupId = "pedido-processador",
    BootstrapServers = "kafka:9092",
    AutoOffsetReset = AutoOffsetReset.Earliest
};

using var consumer = new ConsumerBuilder<string, string>(config).Build();
consumer.Subscribe("pedido-criado");

while (true)
{
    var cr = consumer.Consume();
    var idEvento = cr.Message.Key;

    using var conn = new NpgsqlConnection(envConnString);

    // Bloqueia repetição de evento
    var exists = await conn.ExecuteScalarAsync<bool>(
        "select exists (select 1 from eventos_processados where id = @id)", 
        new { id = idEvento }
    );

    if (exists) continue;

    // Processa pedido
    var payload = JsonSerializer.Deserialize<PedidoCriado>(cr.Message.Value);
    await ProcessarPedido(payload);

    // Marca como processado
    await conn.ExecuteAsync(
        "insert into eventos_processados (id) values (@id)",
        new { id = idEvento }
    );
}

Simples, direto e evita o clássico bug de processar o mesmo evento três vezes em horário de pico.

O Custo da Escolha: Onde Kafka Brilha e Onde Ele Te Derruba

**Kafka é excelente onde produção de eventos é massiva. É péssimo quando sua necessidade é resposta síncrona.**

  • Você ganha reprocessamento, mas perde simplicidade operacional.
  • Você ganha throughput, mas paga com infraestrutura pesada.
  • Você ganha distribuição, mas complica debugging.

Se o problema é comunicação entre microserviços, muitas vezes um simples RabbitMQ — bem configurado — resolve com menos drama.

Direto das Trincheiras

  • Kafka não é fila. Não tente usá-lo como RabbitMQ de grife.
  • Seu microserviço não fica resiliente só porque está atrás de um tópico.
  • Se você não sabe operar Kafka em produção, você não está pronto para usá-lo.

Fontes

Kafka vs PubSub do ponto de vista gerencial : r/ExperiencedDevs,
Kafka vs RabbitMQ | gaGO.io,
‘Não use um banco de dados como uma fila’ : r/dotnet

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! 😉

Deixe um comentário

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