Pular para o conteudo principal

Mensageria e filas

Quando usar fila no lugar de chamada síncrona, como funcionam os padrões principais e por que isso muda a arquitetura de produção.

Andrews Ribeiro

Andrews Ribeiro

Founder & Engineer

Trilha

Trilha de system design para entrevistas

Etapa 8 / 19

O problema

Quando o sistema fica lento sob carga, muita gente tenta resolver só com mais instancia.

As vezes isso ajuda. Muitas vezes não.

Se o trabalho pesado continua no caminho síncrono da requisição, o usuário ainda espera, o timeout ainda existe e o pico ainda derruba o fluxo principal. Escalar a aplicação sem mudar o formato do trabalho e como contratar mais gente para uma fila em que cada pessoa ainda precisa fazer tudo na frente do cliente.

Fila muda esse formato.

Modelo mental

Fila e um buffer entre quem produz trabalho e quem executa trabalho.

O produtor diz “isso precisa acontecer”. O consumidor faz quando consegue. Eles não precisam estar vivos ao mesmo tempo e nem andar na mesma velocidade.

Isso resolve tres dores muito comuns:

  • trabalho pesado no request
  • pico de carga momentaneo
  • dependência lenta ou instável

Pense assim:

  • chamada direta = “faz isso agora e me responde”
  • fila = “anota isso e processa no ritmo certo”

Nem tudo deve ir para fila. Mas tudo que pode sair do caminho principal sem quebrar a experiência merece ser analisado.

Quebrando o problema

Quando usar fila

Fila costuma fazer sentido quando:

  • o usuário não precisa da resposta final imediatamente
  • o trabalho e caro demais para ficar no request
  • você quer absorver pico sem derrubar tudo
  • mais de um consumidor precisa reagir ao mesmo evento

Exemplos classicos:

  • envio de email
  • geração de relatório
  • processamento de imagem
  • indexação de busca
  • notificação

Se o usuário precisa da resposta na hora, talvez fila não seja a solução principal. Ou talvez você precise dividir o fluxo em duas partes: confirmação rápida agora, processamento completo depois.

At-least-once vs exactly-once delivery

Esses nomes assustam mais do que deveriam.

At-least-once significa: a mensagem sera entregue pelo menos uma vez. Na prática, ela pode aparecer de novo.

Exactly-once significa: o sistema promete que a mensagem sera processada uma unica vez do início ao fim. Na teoria e lindo. Na prática, end-to-end de verdade costuma ser caro, raro e cheio de condições.

Por isso, na maioria dos sistemas reais, você assume repetição possível e faz o consumidor aguentar isso sem estrago.

Idempotencia no consumidor

Se a mesma mensagem pode chegar duas vezes, o consumidor precisa saber repetir sem criar dano duplo.

Exemplos:

  • não mandar o mesmo email de confirmação dez vezes
  • não cobrar o mesmo pagamento duas vezes
  • não criar o mesmo pedido de novo

Idempotencia, em linguagem simples, e isso: processar de novo e chegar no mesmo estado final.

Dead letter queue

Dead letter queue, ou fila de falha, e o lugar para onde vai a mensagem que falhou várias vezes.

Sem isso, você corre o risco de:

  • reprocessar para sempre
  • lotar a fila principal
  • esconder erro serio no meio do ruido

Mensagem que foi para dead letter queue não morreu por capricho. Ela virou sinal de que aquele caso precisa de inspeção.

Kafka vs SQS vs RabbitMQ: quando cada um faz sentido

Não precisa decorar catalogo. Basta entender o encaixe.

  • SQS faz muito sentido para trabalho assíncrono simples, com fila gerenciada e baixo atrito operacional.
  • RabbitMQ costuma aparecer bem quando você precisa de roteamento mais detalhado e controle mais fino de mensageria tradicional.
  • Kafka encaixa melhor quando o assunto parece fluxo de eventos em alta escala, retenção de mensagens e vários consumidores lendo o mesmo histórico.

Uma pergunta ajuda:

isso parece “tarefa para ser feita” ou “evento para vários consumidores observarem”?

Se parece tarefa, fila tradicional costuma ser suficiente. Se parece fluxo de eventos e histórico compartilhado, Kafka pode encaixar melhor.

Outra pergunta boa e esta:

eu preciso garantir que alguém execute isso, ou preciso que vários consumidores observem isso?

Ela costuma separar melhor fila de trabalho de stream de eventos do que comparação por marca.

Exemplo simples

Imagine um sistema de pedidos.

Quando o pagamento e aprovado, várias coisas podem acontecer:

  • confirmar o pedido
  • emitir nota
  • mandar email
  • atualizar estoque
  • notificar sistema de analytics

Uma implementação ingênua faria tudo isso dentro do request.

Uma implementação melhor pode:

  1. confirmar o pagamento e salvar o pedido
  2. publicar um evento ou mensagem de order_paid
  3. deixar consumidores separados cuidarem do resto

Agora você ganhou:

  • request mais rápido
  • separação de responsabilidades
  • reprocessamento controlado
  • menos acoplamento entre fluxos

Mas também ganhou responsabilidade:

  • lidar com duplicidade
  • observar falha
  • decidir ordem e garantia

Fila não remove complexidade. Ela move complexidade para um lugar mais administravel.

E isso só vale a pena quando você realmente precisa desse movimento. Se o fluxo e simples, síncrono e barato, fila pode só trocar clareza por operação desnecessaria.

Erros comuns

  • Colocar fila em tudo por reflexo.
  • Assumir que mensagem só chega uma vez.
  • Não ter estratégia para falha repetida.
  • Misturar evento com chamada RPC disfarcada.
  • Achar que adicionar fila resolve regra de negócio mal definida.

Também vale cuidado com o extremo oposto: deixar tudo síncrono só porque “fica mais simples”. Em certo ponto, o sistema paga isso com timeout, pico instável e acoplamento demais.

Como um senior pensa

Quem tem mais experiência costuma fazer duas perguntas cedo:

o usuário precisa dessa resposta agora?

e

se essa mensagem chegar de novo, o que acontece?

Essas duas perguntas limpam boa parte da conversa.

Se a resposta pode vir depois, fila entra como candidata forte. Se repetição cria dano duplo, idempotencia vira obrigatoria.

Tem mais uma pergunta que costuma aparecer cedo na cabeça de quem já apanhou disso:

se o consumidor ficar para tras, o sistema degrada de forma aceitavel ou acumula problema invisível?

Essa pergunta puxa temas como backlog, backpressure e observabilidade, que sao parte real do custo da escolha.

O que o entrevistador quer ver

Em entrevista, mensageria não e só saber desenhar produtor e consumidor.

O entrevistador quer ver se você:

  • sabe quando tirar trabalho do caminho principal
  • entende entrega repetida como comportamento normal
  • pensa em reprocessamento e fila de falha
  • escolhe ferramenta pelo tipo de problema, não pelo nome famoso

Fila boa não e a que deixa o diagrama mais moderno. E a que protege o fluxo principal sem esconder o custo da complexidade.

Resumo rápido

O que vale manter na cabeça

Checklist de pratica

Use isto ao responder

Você concluiu este artigo

Parte da trilha: Trilha de system design para entrevistas (8/19)

Próximo artigo Replicação e sharding sem mistério Artigo anterior RAG vs Fine-Tuning Sem Falso Dilema

Continue explorando

Artigos relacionados