Estratégia de rollback: o passo do deploy que ninguém escreve
Toda equipe tem um pipeline de deploy. Poucas têm uma estratégia de rollback que funcione às 2h da manhã. Rollback não é um script no repo — são triggers, autoridade, caminhos de revert de app e compatibilidade de schema decididos antes do release sair.
Pipelines de deploy são ensaiados a cada sprint. Rollback é documentado uma vez em uma wiki que ninguém abre durante incidentes. A assimetria aparece quando taxas de erro disparam doze minutos após um release: engenheiros debatem se revertem, se a migration é reversível, quem tem autoridade para decidir e se down.sql foi testado contra dados com forma de produção. A estratégia de rollback para deploy é o artefato faltante — não outro script, mas uma árvore de decisão escrita antes do release, com triggers, responsáveis, ações seguras, ações inseguras e passos de verificação curtos o bastante para executar sob pressão.
Rollback de aplicação é rápido quando artefatos são imutáveis e tagueados. Rollback de dados é lento, às vezes impossível, e costuma ser a restrição real. Uma estratégia de rollback que só trata código — "redeploy da tag anterior" — falha na primeira vez que uma migration removeu uma coluna que o binário antigo ainda lê.
Rollback falha quando schema e código se movem juntos sem plano
Deploys modernos tocam duas superfícies: binários de aplicação e schema de banco de dados. Fazem rollback em velocidades distintas e com perfis de segurança distintos.
| Superfície | Mecanismo de rollback | Tempo típico | Risco |
|---|---|---|---|
| Aplicação | Redeploy de tag / imagem anterior | 2–15 minutos | Baixo se o artefato existe |
| Feature flags | Desligar toggle | Segundos | Baixo para caminhos gated por flag |
| Schema (expand) | Código antigo ainda funciona | N/A — forward compatible | Baixo durante fase expand |
| Schema (contract) | Irreversível sem perda de dados | Horas a nunca | Alto |
| Data backfill | Forward fix ou restore | Horas | Muito alto |
Migrations expand/contract existem porque rollback de schema é difícil. Expand adiciona schema novo junto ao antigo — coluna nullable, tabela nova, caminho de dual-write. Migrate move tráfego e dados gradualmente. Contract remove schema antigo só após provar que nada o lê. Rollback durante expand costuma significar reverter código de aplicação deixando colunas novas no lugar — seguro se colunas são nullable e ignoradas por código antigo. Rollback durante contract pode ser impossível sem restore de backup.
Uma down migration que ninguém rodou em staging não é plano de rollback. É esperança.
O padrão de feature flags como infraestrutura de release reduz a necessidade de rollback de código para caminhos user-facing — desligar toggle em segundos. Não reverte mudanças de schema. Flags e estratégia de rollback se complementam; nenhum substitui o outro.
Uma estratégia de rollback é uma árvore de decisão de uma página
O runbook cabe em uma página porque ninguém lê prosa durante incidentes.
Bloco de cabeçalho
- Versão e tag do release
- Identificadores de migrations aplicadas
- Responsável de rollback e autoridade de backup
- Fase expand/contract atual
Triggers — quando fazer rollback
Definir limiares numéricos, não "se algo parecer errado":
- Taxa de erro em endpoints afetados > 2× baseline por 5 minutos
- Latência p99 > 1.5× baseline por 10 minutos
- Qualquer aumento sustentado em taxa de falha de pagamento ou auth
- Falha de teste funcional user-facing pós-deploy
- Trigger manual: engenheiro on-call ou responsável do release
Ramos de decisão
Trigger fired?
├─ Feature-flagged path only → Toggle flag OFF (30 sec)
│ └─ Verify metrics → Done or escalate to app rollback
├─ App bug, schema forward-compatible → Redeploy previous tag
│ └─ Run smoke tests → Monitor 30 min
├─ App bug, schema NOT compatible → Forward-fix OR restore (see unsafe)
└─ Migration caused issue → STOP app rollback if unsafe
├─ Expand phase → Revert app; pause backfill; schema stays
└─ Contract phase → Forward-fix migration; do NOT run down.sql
Ações inseguras — listar explicitamente
- Rodar migrations
downnão testadas contra produção - Dropar colunas para "combinar" com código antigo após dados escritos em schema novo
- Reverter app enquanto workers em background escrevem dados em formato novo
- Restaurar backup de banco de dados sem coordenar versão de app
Verificação após rollback
- Checklist de smoke tests (auth, CRUD core, pagamento se aplicável)
- Comparar taxa de erro e latência com baseline pré-deploy
- Query confirmando ausência de estados de dados órfãos (ex.: linhas presas em status
migrating) - Comunicação: quem notifica stakeholders, o que publicar na status page
Ensaiar a árvore uma vez por trimestre. Rollback não testado é folklore.
Rollback de aplicação requer artefatos imutáveis
Redeploy da versão anterior só funciona se a versão anterior existe e se sabe que é boa.
- Taguear cada deploy de produção:
v1.4.2em imagem de container imutável ou artefato de build. - Registrar a última tag conhecida como boa em release notes — não "o que estava lá antes."
- CI produz o mesmo artefato para uma tag dada para sempre — sem rebuild-from-source durante incidentes salvo falha do registry de artefatos.
- Smoke tests rodam automaticamente contra o deploy novo; definir se bloqueiam ou apenas alertam.
Meta: rollback de aplicação completo em menos de quinze minutos do trigger até recuperação verificada. Se o pipeline leva quarenta minutos, a estratégia de rollback é teórica.
Mudanças de banco de dados usam forward-fix quando rollback para trás é inseguro: enviar uma migration nova que repara estado, manter app na versão falha ou fazer rollback de app separadamente conforme compatibilidade. rollback do Liquibase e arquivos down de frameworks são ferramentas de desenvolvimento — incidentes de produção precisam de caminhos forward revisados, não SQL reverso autogerado contra dados ao vivo.
Rollback de schema coordena com versão de app
A matriz de compatibilidade deve ser escrita antes do deploy:
| Versão app | Versão schema | Seguro? |
|---|---|---|
| N+1 | expand (col nullable nova) | Sim — deploy de app nova |
| N | expand (col nullable nova) | Sim — app antiga ignora col nova |
| N | contract (col removida) | Não — app antiga quebra |
| N+1 | schema N | Geralmente sim se N+1 é backward compatible |
Se a migration N+1 não é backward compatible com app N, rollback simultâneo requer forward-fix, não só revert de tag. Coordenar secrets de CI/CD e acesso ao pipeline — deploys de rollback usam os mesmos caminhos privilegiados que deploys forward; proteger ambos igualmente.
O que deve entrar em um runbook de rollback em produção?
Estes elementos separam recuperação ensaiada de dano improvisado.
Quem pode autorizar rollback?
Nomear autoridade primária e de backup — engenheiro on-call, responsável do release ou lead de engenharia. "Consenso da equipe" não é autoridade às 2h da manhã. Triggers pré-autorizados (desligamento automático de flag em limiar de erro) reduzem debate em caminhos conhecidos.
Quando rollback de app é seguro após uma migration?
Seguro quando a migration está em fase expand e é backward compatible: código antigo ignora elementos de schema novos, sem colunas novas obrigatórias em caminhos de escrita que código antigo usa, sem dados exclusivamente em tabelas novas que código antigo não consegue ler. Inseguro quando fase contract rodou, quando backfill escreveu dados que código antigo interpreta mal, ou quando down migration nunca foi testada.
Qual é o caminho forward-fix quando rollback é impossível?
Documentar: branch hotfix, migration para reparar dados, deploy de versão hotfix de app, queries de verificação, estimativa de timeline. Restore point-in-time de banco de dados é último recurso — nomear RPO/RTO, quem invoca restore, como alinha versão de app com snapshot de dados restaurado.
Uma visão oposta
A postura contrária sustenta que cultura de rollback incentiva deploys imprudentes — que equipes deveriam investir em nunca precisar de rollback com melhor testing, canary deploys e feature flags.
Canary e flags reduzem frequência de rollback. Não eliminam. Misconfiguração de infraestrutura, quedas de terceiros mascaradas como erros de código e edge cases de migration ainda acontecem. Estratégia de rollback é seguro — o objetivo é nunca usá-la; o requisito é que funcione quando necessário.
Zero incidentes de rollback não é a métrica. Tempo médio de recuperação quando rollback é a decisão certa é a métrica.
Key takeaways
- Estratégia de rollback é uma árvore de decisão de uma página — triggers, autoridade, ramos, ações inseguras.
- Rollback de aplicação precisa de artefatos imutáveis tagueados; rollback de schema precisa de disciplina expand/contract.
- Down migrations não testadas em produção não são planos de rollback.
- Feature flags revertem exposição em segundos; não revertem schema.
- Definir triggers numéricos, não "parece ruim" subjetivo.
- Ensaiar rollback trimestralmente; forward-fix é o caminho seguro quando fase contract rodou.
Conclusion
Pipelines de deploy são praticados porque rodam toda semana. Rollback é ignorado porque é desconfortável imaginar falha. Equipes que se recuperam em minutos escreveram a parte desconfortável antes do incidente: o que reverter, o que nunca reverter, quem decide e como verificar recuperação.
O próximo release deve sair com uma seção de rollback nas release notes — não depois. Se a seção está vazia porque "a gente resolve na hora," o release não está pronto.