Corrigindo dados de produção com segurança, com ferramentas reversíveis e auditáveis
Corrigi dezenas de milhares de registros corrompidos em produção (~33k em um caso) sem janela de manutenção, usando comandos CLI reutilizáveis com dry-run, arquivos de rollback, auditoria em lote e republicação de eventos, um padrão de "comando de correção" que o time depois reutilizou.
impacto~33.000 registros corrigidos em produção sem janela de manutenção, com uma trilha de auditoria e rollback disponível.Um padrão reutilizável de "comando de correção" adotado pelo time (vários comandos construídos sobre ele), transformando uma operação arriscada e pontual em uma operação repetível e segura.Consumers downstream reconvergiram sobre os dados corrigidos via republicação de eventos, então as correções ficaram completas de ponta a ponta em vez de só na fonte.Qualitativo: maior confiança na integridade dos dados de produção; correções se tornaram rotineiras e seguras em vez de excepcionais e arriscadas.
01
Contexto
Esta é minha evidência mais forte de maturidade operacional e ownership sobre integridade de dados. Uma correção de dados de produção é uma das coisas de maior risco que uma engenheira faz: é uma escrita em dados reais de clientes sem desfazer, a menos que você construa um. Tratar isso com o rigor de uma funcionalidade, ou seja, reversível, auditável e visualizável antes de aplicar, em vez de um script apressado, é a distinção que quero que isso mostre.
Isso também mostra que otimizo para o time, não só para o incidente: transformei cada correção em ferramentas reutilizáveis, então uma correção pontual virou uma capacidade que outros podiam aplicar com segurança.
02
Problema
Vários bugs distintos tinham deixado dados ruins em produção, por exemplo:
—~33.000 registros com um timestamp armazenado sem informação de timezone, então um campo sensível ao tempo estava errado.
—Linhas duplicadas em uma tabela de relacionamento.
—Registros poluídos por uma execução de teste de uma integração externa.
—Atribuições de ownership incorretas em registros que deveriam ter um único responsável.
03Restrições
+
—Escrever em dados de produção ao vivo não tem desfazer natural. Se uma correção está errada, você corrompeu os dados duas vezes, então reversibilidade precisa ser projetada, não presumida.
—Sem janela de manutenção. O sistema permanecia no ar, então as correções precisavam ser seguras para rodar contra um alvo em movimento e considerar a carga.
—Consumers downstream já tinham ingerido os dados ruins. Corrigir o registro na fonte não basta se consumers orientados a eventos ainda mantêm o valor antigo. Eles precisam ser reconvergidos.
—Algumas correções eram sutis. Uma correção de timezone precisa considerar horário de verão, deduplicação precisa escolher o sobrevivente certo, e backfills grandes precisam ser ritmados para não sobrecarregar o sistema.
04
Decisão
Recusei-me a tratar isso como scripts descartáveis e em vez disso os construí como ferramentas com segurança embutida.
—Dry-run por padrão. Todo comando primeiro reporta exatamente o que *mudaria*, então o efeito é revisado antes de qualquer escrita.
—Um arquivo de rollback escrito antes de qualquer escrita. Cada comando registra o estado anterior em um arquivo de antemão, e um comando dedicado de rollback pode restaurá-lo, então toda correção é reversível.
—Auditoria em lote. Correções rodam em lotes auditados, deixando um rastro do que mudou e quando.
—Republicação enriquecida de eventos. Depois de corrigir um registro na fonte, o comando republica os eventos correspondentes para que consumers orientados a eventos reconvirjam sobre os dados corrigidos em vez de manter o valor antigo.
—Corretude nos detalhes. A correção de timezone considerava horário de verão, a deduplicação escolhia sobreviventes de forma determinística, e um backfill grande usava paginação por cursor e micro-lotes ritmados com concorrência limitada para não sobrecarregar o sistema.
—Rodei-os contra produção com cuidado, diagnosticando as peculiaridades do ambiente containerizado ao executar dentro de pods ao vivo.
05Trade-offs
+
—Dry-run e arquivo de rollback em vez de uma correção direta. Construir preview e desfazer em cada comando custa esforço real antecipado, mas uma escrita em dados de produção sem desfazer é uma aposta que não estou disposta a fazer. Custo aceito: cada comando é mais trabalho do que uma query bruta.
—Republicar eventos em vez de corrigir só as linhas na fonte. Reemitir eventos adiciona uma etapa e alguma carga, mas sem isso os consumers downstream continuam errados e a correção fica só pela metade.
—Comandos reutilizáveis em vez de scripts pontuais. Generalizar em um padrão de "comando de correção" custou mais do que um script para o caso único, e se pagou imediatamente quando o mesmo arcabouço de segurança foi reutilizado na correção seguinte.
—Lotes ritmados em vez de uma escrita em massa única. Paginação por cursor e micro-lotes são mais lentos do que uma única instrução grande, mas mantêm um sistema ao vivo saudável durante um backfill grande.
06
Impacto
—~33.000 registros corrigidos em produção sem janela de manutenção, com uma trilha de auditoria e rollback disponível.
—Um padrão reutilizável de "comando de correção" adotado pelo time (vários comandos construídos sobre ele), transformando uma operação arriscada e pontual em uma operação repetível e segura.
—Consumers downstream reconvergiram sobre os dados corrigidos via republicação de eventos, então as correções ficaram completas de ponta a ponta em vez de só na fonte.
—Qualitativo: maior confiança na integridade dos dados de produção; correções se tornaram rotineiras e seguras em vez de excepcionais e arriscadas.
07Lições Aprendidas
+
Conhecimento de engenharia reutilizável que levo adiante disso:
—Uma correção de dados de produção merece o rigor de uma funcionalidade. Reversibilidade, auditabilidade e um preview não são extras opcionais quando você está escrevendo em dados reais de clientes.
—Dry-run por padrão; escreva o rollback antes da escrita. O desfazer precisa existir antes da mudança, não depois de você descobrir que precisava dele.
—Corrigir a fonte não basta em um sistema orientado a eventos. Republique para que consumers downstream reconvirjam, ou você corrigiu metade do sistema.
—Transforme uma correção em ferramenta. Generalizar uma correção em um comando reutilizável transforma um risco pontual em uma capacidade que todo o time pode aplicar com segurança.
08Evidência
+
—~33k registros corrigidos em produção sem janela de manutenção; trilha de auditoria e rollback disponíveis.
—Padrão de comando de correção (dry-run, arquivo de rollback, republicação de eventos) reutilizado em vários comandos do time.
—Verificado contra o tracker, cinco comandos de correção distintos em vez de um: rotas deixadas com mais de um usuário responsável (2025-10-15), rotas corrompidas por um teste de integração contra um sistema parceiro (2025-12-03 a 12-08), reprocessamento de rotas afetadas pelo novo caminho de atualização parcial (2026-01), usuários corrompidos por um bug de consumer (2026-01-16 a 2026-02-20), e ciclos duplicados removidos (2026-03-19 a 03-25). Esse espalhamento por quatro meses e quatro defeitos de dados distintos é o que faz disso um *padrão*, não um script pontual.
—Fonte: tarefas do Jira no domínio de inspeção, 2025-10 a 2026-03, e os pull requests correspondentes; contagens de registros e os detalhes de rollback/dry-run vêm da base de conhecimento de carreira consolidada (privada).