Pular para o conteudo principal

Transação e fechamento de fronteira: o que fica dentro e o que deve sair

Transação não existe para abraçar tudo que acontece no fluxo; ela existe para fechar uma fronteira de consistência com critério.

Andrews Ribeiro

Andrews Ribeiro

Founder & Engineer

O problema

Muita discussão sobre transação vira uma mistura perigosa de intenções.

O time quer:

  • gravar no banco
  • publicar evento
  • chamar gateway externo
  • enviar email
  • atualizar cache

e gostaria de pensar nisso tudo como uma operação única.

O problema é que o sistema real não funciona assim.

Banco até pode participar de uma transação local.

Provider externo, fila, webhook e email não entram magicamente nessa mesma garantia.

Modelo mental

Transação é uma fronteira de consistência local.

Ela responde:

quais mudanças precisam sair juntas do ponto de vista deste armazenamento?

Essa é uma pergunta mais útil do que:

como eu faço tudo acontecer sem risco nenhum?

Porque a segunda costuma empurrar o time para promessas irreais.

O que normalmente fica dentro

Dentro da transação costumam fazer sentido coisas como:

  • criar ou atualizar registros que precisam nascer coerentes entre si
  • reservar estado local
  • registrar fato interno que depende do mesmo commit
  • persistir um outbox na mesma unidade local

Exemplo:

  • criar pedido
  • gravar itens
  • marcar estoque reservado
  • persistir evento no outbox

Tudo isso ainda é estado do seu lado.

Faz sentido fechar junto.

O que normalmente deve sair

Fora da transação costumam ficar:

  • chamada HTTP para outro sistema
  • envio de email
  • publicação em broker fora do mesmo commit local
  • recálculo pesado
  • atualização de cache compartilhado

Não porque essas coisas são menos importantes.

Mas porque elas não obedecem à mesma mecânica de commit do banco.

Quando você tenta tratá-las como se obedecessem, começa a vender consistência que não existe.

Exemplo simples

Imagine “confirmar pagamento do pedido”.

Uma fronteira razoável pode ser:

  • gravar pagamento aprovado
  • mudar pedido para paid
  • registrar evento order_paid no outbox

Isso fecha um estado interno consistente.

Depois do commit:

  • worker publica o evento
  • email sai
  • ERP é avisado

Se o email falhar, o pedido continua pago.

Se o ERP atrasar, o sistema ainda sabe o que já foi confirmado.

Isso é muito mais honesto do que tentar empacotar tudo na mesma ilusão de atomicidade.

O erro comum

O erro comum é segurar a transação enquanto espera coisa demais:

  • chamada externa
  • cálculo pesado
  • retry improvisado
  • lógica de compensação mal definida

O resultado costuma ser:

  • lock por tempo demais
  • throughput pior
  • timeout
  • estado difícil de entender

Transação longa raramente deixa o sistema “mais seguro”.

Frequentemente deixa o sistema mais frágil.

Outbox entra justamente aqui

Outbox ajuda porque separa duas coisas:

  • confirmar o estado local
  • propagar esse fato para fora

Isso evita o clássico problema de:

  • commit no banco deu certo
  • publicação do evento falhou

Você não resolve tudo.

Mas pelo menos torna a fronteira explícita e reprocessável.

Como um senior pensa

Quem tem mais experiência normalmente pergunta:

  • o que realmente precisa sair consistente neste commit?
  • o que pode reagir depois?
  • o que é local e o que já é integração?
  • se der falha no meio, consigo explicar o estado final sem inventar desculpa?

Essa pergunta é melhor do que abrir a conversa com:

“vamos colocar tudo dentro de uma transação”

Ângulo de entrevista

Esse tema aparece muito em system design, backend e debugging de produção.

O entrevistador quer perceber se você sabe:

  • separar consistência local de side effect externo
  • evitar transação longa demais
  • pensar em outbox, retry e reprocessamento com clareza
  • explicar o que é garantido e o que é eventual

Resposta forte parece algo como:

“Eu fecharia em transação só o estado interno que precisa sair coerente no banco. O que depende de sistema externo eu trataria como efeito posterior, idealmente com outbox e reprocessamento, para não fingir atomicidade que eu não controlo.”

Isso mostra julgamento.

Takeaway direto

Transação boa não é a que tenta proteger o mundo inteiro.

É a que fecha bem a fronteira que realmente está sob seu controle.

Resumo rápido

O que vale manter na cabeça

Checklist de pratica

Use isto ao responder

Você concluiu este artigo

Próximo artigo Fronteira entre consistência forte e aceitação operacional no backend Artigo anterior Fila justa vs throughput em semáforos por recurso sem fingir que dá para maximizar tudo

Continue explorando

Artigos relacionados