Esta lição instala as duas formas de desfazer um deploy que deu errado: Flag específica que desliga a feature principal em emergência. Ex: bug crítico em produção → liga `WEDGE_ENABLED: false` → usuário vê página de manutenção → você conserta sem pressa. e Promover um deploy anterior pra produção, revertendo o atual. `vercel rollback <url-anterior>` faz isso em menos de 1 minuto, sem rebuild e sem espera..
Você lança. Algo dá errado. Quanto tempo até desfazer?
Se a resposta é "uma hora pra reverter o git, rebuild, redeploy", você não vai lançar com frequência, porque o medo de subir custa demais. Se a resposta é "30 segundos", você lança 10x por dia e dorme tranquilo.
deploy → flag → deploy → flag: quando reverter é barato, lançar vira rotina
Esta lição instala duas redes de segurança que tornam o deploy coisa rotineira:
Kill switch: botão que desliga a feature principal em emergência. Bug ruim em produção? Liga WEDGE_ENABLED: false, redeploya em 2 min, usuário vê "em manutenção", sem pressa pra consertar.
Rollback: comando que volta pra versão anterior em <1 min. Sem rebuild, sem espera. Vai testar isso em produção (a lição guia o fazer e desfazer com segurança).
Documentação em docs/runbook.md: pra você lembrar como fazer cada um quando precisar.
Não é teoria: você roda os dois e confirma que funcionam.
Cria `src/config/features.ts` com:
export const FEATURES = {
// Liga/desliga UI da fatia 1 inteira (escotilha de emergência)
WEDGE_ENABLED: true,
// Pedaço novo que ainda não está pronto pra todo mundo
EXPERIMENTAL_REPORT_VIEW: false,
} as const
export type FeatureKey = keyof typeof FEATURES
Mostre o diff antes de criar.
Aprove. As duas flags servem propósitos diferentes:
WEDGE_ENABLED = kill switch. Se você descobre em produção que o fluxo principal tem bug crítico (ex: inserindo CPF com dígito errado), liga false, redeploya em 2 minutos, e o usuário vê uma página de "fora do ar pra manutenção" em vez do bug. É grosso, mas resolve enquanto você conserta com calma.
EXPERIMENTAL_REPORT_VIEW = feature em desenvolvimento. Você quer comitar código novo sem expor pro usuário ainda. Mantém false enquanto trabalha; liga true quando estiver pronto.
A primeira flag (WEDGE_ENABLED) precisa estar no caminho que importa pra ter valor.
prompt · text
Adiciona o check de `FEATURES.WEDGE_ENABLED` no ponto onde o usuário acessa a fatia 1. Caso típico: `app/[recurso]s/novo/page.tsx` ou rota equivalente.
Quando `WEDGE_ENABLED === false`, renderiza uma página simples (Server Component) com:
- Mensagem em pt-BR: "Esta funcionalidade está em manutenção. Volta em breve."
- Botão pra voltar pra home
- HTTP status 503 se possível (`Response`-based; pode ser difícil em App Router — se for, deixa 200)
Quando `WEDGE_ENABLED === true`, renderiza normalmente.
Mostre o diff antes de aplicar.
Aprove. Testa local:
Roda npm run dev
Acessa a rota da fatia 1: funciona normal
Muda WEDGE_ENABLED: true pra false em src/config/features.ts
Agora a outra metade: desfazer um deploy. Pra testar isso na prática, você precisa de 2 deploys recentes em produção. Provavelmente já tem (L02 + L03 + L04 + L05 = vários deploys). Confirma:
prompt · text
Roda `vercel ls` e mostra os últimos 5 deploys de produção (target = production). Anota o URL do penúltimo deploy — vamos usar como destino do rollback de teste.
Agora o teste:
prompt · text
Vou testar rollback. Antes de rodar, me explica em 3 linhas o que `vercel rollback <deployment-url>` faz e se é reversível. Não roda ainda — só explica.
Leia a explicação. vercel rollback promove o deploy especificado pra produção (na URL principal), substituindo o atual. É reversível: você pode rollback de novo pro mais recente, ou redeployar.
prompt · text
Agora roda o rollback. Em sequência:
1. `vercel rollback <url-do-penultimo-deploy>`
2. Aguarda 30 segundos
3. `curl -I https://<dominio-de-producao>/` (ou /docs/<rota>) e mostra os headers
4. Confirma que o site agora está servindo o conteúdo do deploy anterior
Mostra cada passo do output.
Aprove. Se passou, abre o site no browser; deve mostrar a versão anterior (o que muda depende do que você fez entre os dois deploys).
Agora reverte pra produção atual:
prompt · text
Reverte o rollback — promove o deploy mais recente de volta pra produção. `vercel ls` pra confirmar e `vercel rollback <url-mais-recente>` (ou `vercel promote <url-mais-recente>`). Confirma com curl + browser que voltou pro estado atual.
Aprove. Site de volta ao normal. Você acabou de provar pra si que rollback funciona em < 1 minuto.
Cria ou atualiza `docs/runbook.md` com:
# Runbook — operações comuns
## Rollback de deploy
Quando: deploy quebrou produção (erro 500 generalizado, regressão visível, dado corrompendo).
Procedimento (< 1 minuto):
1. `vercel ls` — pega o URL do penúltimo deploy de produção
2. `vercel rollback <url-anterior>` — promove o anterior
3. Confirma no browser que voltou
4. Em paralelo: identifica e corrige o bug; redeploya com fix
## Kill switch
Quando: a fatia 1 tem bug crítico mas o resto do site está OK (ex: form criando registro com dado errado).
Procedimento:
1. Edita `src/config/features.ts`: `WEDGE_ENABLED: false`
2. Commit, push, deploy (Vercel auto-deploya em ~2 min)
3. Confirma no browser que mostra a página de manutenção
4. Conserta o bug, reverte pra `true`, redeploya
Mostre o diff antes de criar.
Faça commit das mudanças: `src/config/features.ts`, ajuste na rota da fatia 1 que usa a flag, e `docs/runbook.md`. Mensagem: `feat(release): feature flags + rollback procedure tested`. Mostra os comandos antes.
O CEAP foi lançado em 5 fases (Visão Geral → Deputados → Padrões → Rede + Metodologia → DeepDive), e cada transição entre fases é mudar false pra true em src/config/features.ts. Trecho do MAINTENANCE.md:
Note o que isso destravou na narrativa: o autor publicou primeiro só "Visão Geral" (Fase 1). Conseguiu feedback do público numa superfície pequena, sem comprometer o resto do produto. Cada fase seguinte foi 1 commit no features.ts + deploy, em vez de 1 mês de desenvolvimento separado. O código das outras fases já estava em produção desde a Fase 1, escondido atrás das flags.
Deploy frequente e Variável booleana que liga/desliga um pedaço do produto. Você faz deploy de código novo escondido atrás de `if (FEATURES.X)`; ativar é mudar `false` pra `true`. Permite lançar sem expor. andam juntos. Sem flags, você não consegue fazer commit ou deploy de feature parcial. Com flags, você deploya cedo, ativa quando preferir, e trabalha em features grandes sem manter uma branch viva por semanas.