en
· 4 min de leitura

Quando adicionar um message broker, e quando você está fugindo de uma decisão

O que um broker compra, o que custa, e o sinal de que a fila está ali para evitar decidir quem é dono do dado.

system-design

Alguém no time diz: a gente devia colocar uma fila entre esses dois serviços. Soa como arquitetura. Às vezes é. Muitas vezes é um jeito de adiar uma pergunta que ninguém quer responder. Já revisei sistemas suficientes para reconhecer a diferença, e quero listar os sinais.

O que um broker compra de verdade

Um message broker te dá quatro coisas concretas. Desacoplamento no tempo: o produtor escreve enquanto o consumidor está fora do ar, e o consumidor recupera o atraso depois. Buffer: um pico de dez mil pedidos vira backlog em vez de uma onda de 503. Fan-out: um evento, cinco consumidores, nenhum dos quais o produtor precisa conhecer. Retries com backoff e dead letter, cuidados pela infraestrutura em vez de por loops feitos à mão.

Se você precisa de pelo menos duas dessas coisas, e consegue nomeá-las, o broker provavelmente é a escolha certa. Se só consegue dizer 'é mais escalável', você ainda não tem um motivo.

O que custa

Cada um desses benefícios tem uma conta. A ordenação vira condicional: a maioria dos brokers garante ordem por partição ou por chave, não global, e no momento em que você adiciona um segundo consumidor ganha paralelismo e perde sequência. Duplicatas viram rotina, então todo consumidor precisa ser idempotente, o que é uma disciplina inteira à parte. A visibilidade cai: uma chamada síncrona falha na sua cara, uma assíncrona falha numa dead letter queue que você precisa lembrar de olhar.

O broker também é mais um sistema para operar, com upgrades, disco, partições, rebalanceamento de consumer group e chamados às 2 da manhã. E as mensagens são um contrato. Quando três consumidores dependem do formato de order.created, mudar um campo é um projeto de versionamento, não uma edição.

O sinal: uma fila no lugar de uma decisão

Este é o padrão que mais vejo. Dois times não conseguem concordar sobre quem é dono de um dado ou de uma transação. Em vez de decidir, colocam um evento entre eles. O serviço A publica 'aconteceu tal coisa', o serviço B consome e atualiza a própria cópia. Agora ninguém é dono da verdade, as duas cópias divergem, e a fila é onde a discordância vai se esconder.

A outra versão: uma operação que deveria ser uma transação só é dividida em 'salvar o pedido' e 'publicar o evento', sem outbox, então o evento às vezes se perde e às vezes é publicado para um pedido que sofreu rollback. O broker não criou essa inconsistência. Só tornou ela invisível.

Pergunte direto: qual é a fonte de verdade desse dado, e onde está a fronteira da transação? Se a fila é a resposta para qualquer uma das duas, não é resposta, é adiamento.

Comece com uma tabela

Para boa parte dos casos, uma tabela de jobs no Postgres é o primeiro broker certo. Insira uma linha na mesma transação da mudança de negócio, assim o job nunca existe sem o dado nem o dado sem o job. Workers fazem polling com SELECT ... FOR UPDATE SKIP LOCKED, que deixa vários workers puxarem da mesma tabela sem pisar um no outro. Retries são um contador de tentativas, dead letter é uma coluna de status, visibilidade é uma query, ordenação é um índice. Não há nada novo para operar.

Isso aguenta milhares de jobs por minuto com folga em hardware comum, e existem bibliotecas para toda stack relevante. A maioria dos sistemas que audito nunca cresce além disso, e os que crescem entendem muito melhor os próprios requisitos na hora de sair.

Quando o broker de verdade é a escolha certa

  • O volume é genuinamente alto, na casa das dezenas de milhares de mensagens por segundo.
  • Você precisa de fan-out para muitos consumidores independentes que vão mudar com o tempo.
  • Produtores e consumidores pertencem a times diferentes, com ciclos de deploy diferentes.
  • Você precisa de replay do histórico, que brokers em estilo de log fazem bem e tabelas fazem mal.
  • A carga é um stream, não um conjunto de jobs, e você quer janelas e processamento de stream.

Mesmo assim, mantenha o padrão outbox do lado do produtor. O broker não resolve a atomicidade entre seu banco e o log. Só uma transação resolve.

A pergunta nunca é 'devemos usar uma fila'. É 'o que essa fila nos permite parar de decidir', e se essa é uma decisão que temos permissão para adiar.