Pular para o conteudo principal

Ordem, causalidade e replays internos sem assumir sequência perfeita

Quando backend trata ordem de entrega como verdade absoluta, retry, atraso e replay viram bug difícil de explicar.

Andrews Ribeiro

Andrews Ribeiro

Founder & Engineer

O problema

Tem muito backend que funciona assim:

  • evento chega
  • handler aplica
  • próximo evento chega
  • handler aplica

Enquanto tudo chega na ordem esperada, parece ótimo.

O problema começa quando aparece a vida real:

  • retry
  • atraso
  • duplicação
  • replay
  • consumidor paralelo

Nesse ponto, a sequência perfeita some.

Modelo mental

Vale separar três coisas que muita equipe mistura:

  • ordem de entrega
  • causalidade de negócio
  • ordem em que o sistema consegue reprocessar

Entrega é infraestrutura.

Causalidade é regra do domínio.

Replay é operação.

Se o sistema trata as três como se fossem a mesma coisa, qualquer atraso vira comportamento estranho.

Exemplo simples

Imagine um fluxo de assinatura.

Você tem eventos como:

  • SubscriptionCreated
  • PaymentConfirmed
  • SubscriptionCanceled

Agora imagine que:

  • o cancelamento chega antes da confirmação por atraso
  • depois roda replay do histórico
  • no meio disso, uma confirmação duplicada reaparece

Se o consumidor só “aplica o que chegou por último”, você pode:

  • reabrir assinatura cancelada
  • recalcular status errado
  • disparar efeito colateral de novo

O problema não foi só a fila.

O problema foi confiar que a ordem de entrega carregava a causalidade inteira.

O erro comum

O erro comum é dizer:

“mas nossa partição preserva ordem”

Preserva ordem dentro de um recorte específico.

Não resolve automaticamente:

  • replay histórico
  • múltiplas origens
  • reprocessamento seletivo
  • mensagens atrasadas
  • concorrência entre consumidores

Outro erro comum é usar created_at de transporte como se fosse versão de negócio.

Nem sempre o último a chegar é o último que deveria valer.

O que normalmente ajuda

Normalmente ajuda quando o sistema passa a ter critério explícito para decidir:

  • se esse evento ainda é válido
  • se ele já foi aplicado
  • se ele chegou velho demais
  • se falta algum predecessor relevante

Na prática, isso costuma aparecer como:

  • versão por entidade
  • sequência monotônica por agregado
  • regra de ignorar evento obsoleto
  • handler idempotente
  • replay com isolamento operacional

Não precisa transformar tudo em teoria de distributed systems.

Precisa só parar de fingir que a sequência sempre vai cooperar.

Como um senior pensa

Quem já sofreu com isso costuma perguntar:

  • este fluxo depende de ordem perfeita ou sabe sobreviver sem ela?
  • o que define “mais novo” aqui: entrega, versão ou regra de negócio?
  • se eu rodar replay amanhã, o sistema refaz estado ou duplica confusão?
  • tenho sinal claro de mensagem atrasada ou velha demais?

Essa conversa muda bastante o desenho.

Ângulo de entrevista

Esse tema aparece em system design, eventos, jobs, filas e incidentes.

O entrevistador quer ver se você entende:

  • que ordem de transporte não substitui regra de negócio
  • que replay muda a forma de pensar handler
  • que backend maduro precisa tolerar fora de ordem em algum nível

Resposta forte costuma soar assim:

“Eu não assumiria sequência perfeita. Tentaria separar causalidade de negócio da ordem de entrega e colocaria algum critério explícito, como versão por entidade, idempotência e rejeição de evento obsoleto, principalmente se o fluxo puder sofrer replay ou atraso.”

Takeaway direto

Sistema interno bom não é o que nunca recebe coisa fora de ordem.

É o que não entra em pânico quando isso acontece.

Resumo rápido

O que vale manter na cabeça

Checklist de pratica

Use isto ao responder

Você concluiu este artigo

Próximo artigo Orquestração interna de fluxo longo Artigo anterior Orçamento de latência por fluxo interno sem cada etapa roubar o tempo todo

Continue explorando

Artigos relacionados