Todo o engenheiro de dados vive, mais cedo ou mais tarde, o mesmo pesadelo: um pipeline falhou a meio da noite, alguém o voltou a correr para recuperar, e de manhã os relatórios mostram vendas a dobrar. Não houve mais vendas — houve dados duplicados porque o pipeline foi corrido duas vezes. Este problema tem nome e tem solução: chama-se idempotência, e é talvez a propriedade mais importante e menos falada de um pipeline fiável.
O que é idempotência
Um processo é idempotente quando corrê-lo uma vez ou várias vezes produz exatamente o mesmo resultado. Carregar os dados de um dia deveria deixar a base de dados no mesmo estado, quer corras esse carregamento uma vez, quer o corras cinco vezes por engano. Se o segundo carregamento duplica os dados, o pipeline não é idempotente — e é uma bomba-relógio à espera do dia em que alguém tiver de o repetir.

Porque isto importa mais do que parece
Num mundo perfeito, cada pipeline corria uma vez e nunca falhava. No mundo real, falham — uma ligação cai, uma fonte atrasa-se, um servidor reinicia — e a resposta natural é voltar a correr. Se o pipeline não for idempotente, cada recuperação cria um problema novo. E como as falhas acontecem sempre nos piores momentos, a duplicação descobre-se tarde, já contaminada em relatórios e decisões. A idempotência é a rede de segurança que torna a recuperação segura em vez de perigosa.
O padrão mais comum: apagar e reinserir
A forma mais simples e robusta de garantir idempotência é o padrão "delete-insert" por partição. Em vez de acrescentar cegamente os dados novos, o pipeline primeiro apaga os dados do período que vai carregar (por exemplo, os de hoje) e só depois os insere. Assim, correr o carregamento de hoje duas vezes deixa sempre exatamente um conjunto de dados de hoje — o segundo carregamento apaga o que o primeiro pôs e volta a pôr o mesmo. Simples, previsível, à prova de repetições.
A alternativa: upsert por chave
Quando não há uma partição limpa por período, usa-se o "upsert": para cada registo, se já existe (identificado por uma chave única), atualiza-se; se não existe, insere-se. O resultado é o mesmo — correr duas vezes não duplica, porque a segunda passagem apenas reescreve por cima o que já lá estava. Exige ter chaves fiáveis, mas dá idempotência mesmo em fluxos onde os dados chegam misturados.
Cuidados que fazem a diferença
- Definir a granularidade certa: a partição a apagar e reinserir deve corresponder ao que o pipeline processa de cada vez — nem a mais (apagas dados que não devias), nem a menos.
- Tornar a operação atómica: o apagar e o inserir devem acontecer como um todo, para que uma falha a meio não deixe a base num estado inconsistente.
- Pensar nos dados a jusante: se outros processos leem estes dados, a substituição deve ser invisível para eles — não podem apanhar o momento em que os dados estão apagados mas ainda não reinseridos.
Um caso concreto
Uma empresa tinha um pipeline noturno que acrescentava as vendas do dia à tabela histórica. Funcionou durante meses — até à noite em que a fonte atrasou, o pipeline falhou a meio, e a equipa de operações, seguindo o procedimento, o voltou a correr. Ao amanhecer, as vendas do dia anterior apareciam duplicadas, e como a duplicação não era óbvia (os totais só pareciam "um bom dia"), demorou até alguém desconfiar. A correção envolveu identificar e apagar os registos duplicados à mão, com o risco de apagar os errados. Depois deste susto, reescreveram o pipeline com o padrão delete-insert por dia. Da vez seguinte que falhou e teve de ser repetido, não aconteceu absolutamente nada — os dados ficaram corretos, sem intervenção. O custo de tornar o pipeline idempotente pagou-se na primeira recuperação tranquila.
Idempotência é uma mentalidade, não um truque
O verdadeiro valor não está numa técnica específica, mas no hábito de desenhar cada pipeline a pensar "e se isto correr duas vezes?". Essa pergunta, feita no início, muda a arquitetura para melhor e poupa noites em claro depois. Pipelines idempotentes recuperam-se sozinhos, toleram falhas sem drama e dão a quem os opera a tranquilidade de poder repetir sem medo. É a diferença entre um sistema frágil e um sistema robusto.
Na prática
Faz um exercício simples com o teu pipeline mais crítico: se o corresses agora, outra vez, sobre dados que já processou, o que aconteceria? Se a resposta for "duplicava" ou "não sei", encontraste a tua próxima melhoria — e provavelmente evitaste um pesadelo futuro. Os teus pipelines aguentam ser corridos duas vezes, ou vivem à espera do dia em que alguém tiver de os repetir?