Idempotência
Uma operação é idempotente quando executá-la uma vez ou dez vezes produz o mesmo estado
final. mkdir -p /opt/app é idempotente; mkdir /opt/app não é — a segunda execução
falha. A distinção parece pedante até o dia em que a rede cai no meio de um apply e você
precisa decidir se pode rodar de novo.
É aí que a propriedade mostra o valor real: idempotência é o que torna a repetição segura, e repetição é a única coisa que a automação sabe fazer bem diante de falha.
Por que a automação depende disso
Seção intitulada “Por que a automação depende disso”Sistemas distribuídos falham no meio, sempre. O cliente envia uma requisição, a rede cai antes da resposta chegar, e ele não sabe se a operação aconteceu. Só existem duas saídas: tentar de novo, ou desistir.
Se a operação for idempotente, tentar de novo é gratuito. Se não for, cada tentativa pode criar um recurso duplicado, cobrar o cliente duas vezes ou disparar dois e-mails. É por isso que retry seguro é uma consequência da idempotência, e não uma técnica independente — retry sobre operação não idempotente não é robustez, é dano multiplicado.
O mesmo raciocínio explica por que Kubernetes e Terraform são declarativos: um controlador que reconcilia estado desejado pode rodar continuamente, sem coordenação, porque cada execução converge para o mesmo lugar.
Onde ela falta, e o que quebra
Seção intitulada “Onde ela falta, e o que quebra”- No pipeline. Um estágio que executa
POST /criar-recursosem chave de idempotência duplica na primeira reexecução — e reexecutar job é a coisa mais comum do mundo em CI. - Em IaC. Um
local-execcomcurl -X POST, ou uma task Ansible comshell:semcreates:, quebra a propriedade de todo o resto. Oapplydeixa de ser repetível. - Em migrations. Um script sem controle de versão aplicado duas vezes pode duplicar dados ou falhar no meio, deixando o esquema num estado que ninguém previu.
- Em consumidores de fila. Praticamente toda fila entrega pelo menos uma vez. Se o worker não for idempotente, mensagem reentregue vira cobrança dobrada.
O padrão comum a todos: alguém assumiu que a operação aconteceria exatamente uma vez. Em sistemas distribuídos, “exatamente uma vez” é uma promessa que a infraestrutura não consegue cumprir sozinha — ela é construída em cima de entrega pelo menos uma vez, com idempotência do lado de quem recebe.
Como se constrói
Seção intitulada “Como se constrói”Três mecanismos cobrem quase todos os casos:
Verificar antes de agir. É o que os módulos declarativos fazem: consultar o estado
atual e agir só na diferença. state: present do Ansible, resource do Terraform,
CREATE TABLE IF NOT EXISTS.
Chave de idempotência. O cliente gera um identificador único da intenção e o envia junto; o servidor guarda o resultado da primeira execução e devolve a mesma resposta para repetições da mesma chave. É como APIs de pagamento sérias funcionam.
POST /cobrancasIdempotency-Key: 9f3a2c-pedido-4821Operação naturalmente idempotente. SET saldo = 100 é repetível; saldo = saldo + 10
não é. Sempre que a modelagem permitir, prefira declarar o valor final a aplicar um delta.
O limite honesto
Seção intitulada “O limite honesto”Idempotência não é gratuita nem sempre possível.
Ela custa estado: a chave de idempotência precisa ser guardada, com prazo de validade e armazenamento, e isso é infraestrutura a mais. Ela também não garante ordem — duas operações idempotentes aplicadas fora de ordem ainda produzem resultado errado; para isso existem versionamento otimista e sequenciamento.
E há efeitos que são irredutivelmente não idempotentes: enviar e-mail, cobrar cartão, disparar uma chamada externa. Nesses casos, a idempotência vive na borda — você registra que já enviou, antes ou junto do envio, e consulta esse registro antes de repetir. O problema não desaparece; ele se move para um lugar onde você consegue tratá-lo.
Por fim, cuidado com o falso idempotente: um script que “verifica antes” com uma consulta e
age em seguida tem uma janela entre a verificação e a ação. Sob concorrência, os dois
caminhos passam pela verificação e agem. A correção é uma operação atômica no armazenamento
(INSERT ... ON CONFLICT, lock, compare-and-swap), não um if melhor escrito.
Leituras relacionadas
Seção intitulada “Leituras relacionadas”- Falha parcial e sistemas distribuídos — por que a repetição é inevitável
- Build reprodutível — a mesma ideia aplicada a artefatos
- Princípios de IaC — idempotência como base do declarativo
- Ansible — verificando idempotência na prática