Feature flags no código: desacoplando deploy de release
1. O Problema: Quando Deploy e Release São a Mesma Coisa
1.1. Riscos de deploys monolíticos: rollbacks forçados e downtime
Em times que não utilizam feature flags, cada deploy é também uma release. Isso significa que, ao fazer o merge de uma branch com código novo para main, a funcionalidade vai automaticamente para produção. Se algo der errado, o rollback exige reverter commits inteiros, o que pode causar downtime prolongado.
# Cenário sem feature flags: deploy = release
git checkout -b feature/nova-busca
# ... desenvolve e commita código incompleto ...
git checkout main
git merge feature/nova-busca
git push origin main
# Agora o código incompleto está em produção!
1.2. Dependência entre branches e ciclos de release
Sem flags, as equipes ficam reféns de ciclos de release rígidos. Uma funcionalidade que depende de outra precisa esperar ambas estarem prontas. Isso gera branches longas, conflitos de merge e retrabalho.
1.3. Conflitos entre equipes: código incompleto vs. necessidade de deploy
Enquanto o time de frontend precisa fazer deploy de uma correção urgente, o time de backend ainda está desenvolvendo uma nova API. Sem flags, ou o deploy é adiado ou o código incompleto vai para produção.
2. Conceito de Feature Flags no Contexto do Git
2.1. O que é uma feature flag: variável de controle no código
Uma feature flag é uma variável que controla se um trecho de código deve ser executado ou não. No Git, isso significa que você pode commitar código novo sem ativá-lo imediatamente.
2.2. Diferença entre flag de release e flag experimental
- Flag de release: controla quando uma funcionalidade pronta vai para produção.
- Flag experimental: ativa funcionalidades em desenvolvimento para testes internos.
2.3. Exemplo mínimo: if feature_enabled("nova-busca") no código
# config/flags.yaml
features:
nova-busca: false
dark-mode: true
# app/busca.py
from config import flags
def realizar_busca(termo):
if flags.feature_enabled("nova-busca"):
return nova_busca(termo)
else:
return busca_legado(termo)
3. Estratégias de Branch com Feature Flags
3.1. Trabalhando em main com flags desligadas até o fim
Com feature flags, você pode trabalhar diretamente em main ou em branches curtas. O código novo fica atrás de uma flag desligada.
git checkout main
git pull origin main
# Adiciona código da nova funcionalidade com flag desligada
git add app/nova_busca.py config/flags.yaml
git commit -m "feat: implementa nova busca (desligada por padrão)"
git push origin main
3.2. Merge contínuo sem branches de feature longas
Em vez de manter uma branch feature/nova-busca por semanas, você faz merges frequentes para main com a flag desligada. Isso reduz conflitos e facilita revisões.
# Dia 1: estrutura básica
git commit -m "feat: adiciona estrutura da nova busca (flag off)"
# Dia 2: lógica principal
git commit -m "feat: implementa algoritmo de busca (flag off)"
# Dia 3: testes e ajustes
git commit -m "fix: corrige edge case na nova busca (flag off)"
3.3. Removendo flags após estabilização: como e quando no Git
Quando a funcionalidade está estável, remova a flag e o código legado.
# 1. Ativa a flag em produção
git commit -m "feat: ativa nova busca para 50% dos usuários"
# 2. Após validação, remove a flag e código antigo
git rm app/busca_legado.py
# Remove a condição if do código
git commit -m "feat: remove flag nova-busca e código legado"
4. Gerenciamento de Flags no Repositório Git
4.1. Armazenando configuração de flags: arquivos YAML/JSON versionados
Mantenha as flags em arquivos versionados para rastrear mudanças no Git.
# config/flags.yaml
version: 2.3.0
flags:
nova-busca:
enabled: false
description: "Nova engine de busca"
owner: "@time-busca"
dark-mode:
enabled: true
description: "Modo escuro"
owner: "@time-ui"
4.2. Commits de ativação/desativação de flags
Cada mudança de estado de flag deve ser um commit claro.
git commit -m "feat: enable pagination v2 for 10% users"
git commit -m "fix: disable pagination v2 due to timeout issue"
git commit -m "chore: remove flag pagination-v2 after stabilization"
4.3. Tags de release com estado de flags
Use tags para marcar releases com o estado das flags.
git tag -a v2.3.0-flags-off -m "Release v2.3.0 com flags desligadas"
git tag -a v2.4.0-flags-on -m "Release v2.4.0 com flags ativadas"
5. Deploy Seguro com Rollback via Flags
5.1. Usando git revert em uma flag (alteração de configuração) vs. código inteiro
Para desativar uma flag, basta reverter o commit de configuração, não o código inteiro.
# Commit que ativou a flag
git log --oneline
# a1b2c3d feat: enable pagination v2
# Reverte apenas a ativação
git revert a1b2c3d
git commit -m "fix: disable pagination v2 (rollback via flag)"
5.2. Hotfix com flag: desligar recurso sem reverter commit
Em vez de reverter commits de funcionalidades, apenas desligue a flag.
# Em produção, a flag está ativa
# Para desligar rapidamente:
echo "features:\n pagination-v2: false" > config/flags.yaml
git add config/flags.yaml
git commit -m "hotfix: disable pagination v2 due to performance issue"
5.3. Exemplo prático: deploy de duas versões, uma com flag ativa
# Versão A: flag desligada (deploy padrão)
git tag v2.3.0-stable
# Versão B: flag ativada (deploy para teste)
git checkout v2.3.0-stable
echo "features:\n pagination-v2: true" > config/flags.yaml
git add config/flags.yaml
git commit -m "feat: enable pagination v2 for testing"
git tag v2.3.0-test
6. Integração com Git Bisect e Automação
6.1. Identificando regressões em flags: git bisect sobre commits de configuração
git bisect start
git bisect bad HEAD
git bisect good v2.2.0
# O bisect vai testar commits. Se o bug só aparece com flag ativa:
# O commit ruim será o que ativou a flag
6.2. Scripts de teste que respeitam estado de flags
#!/bin/bash
# test_with_flags.sh
FLAGS_FILE="config/flags.yaml"
# Testa com flags desligadas
cp $FLAGS_FILE ${FLAGS_FILE}.backup
echo "features:\n nova-busca: false" > $FLAGS_FILE
pytest tests/
# Testa com flags ativadas
echo "features:\n nova-busca: true" > $FLAGS_FILE
pytest tests/
# Restaura configuração original
mv ${FLAGS_FILE}.backup $FLAGS_FILE
6.3. Pipeline CI/CD com variáveis de ambiente para flags
# .gitlab-ci.yml
stages:
- test
- deploy
variables:
FEATURE_NOVA_BUSCA: "false"
test:
script:
- echo "features:\n nova-busca: $FEATURE_NOVA_BUSCA" > config/flags.yaml
- pytest tests/
deploy:
script:
- ansible-playbook deploy.yml -e "flag_nova_busca=$FEATURE_NOVA_BUSCA"
7. Boas Práticas e Armadilhas Comuns
7.1. Evitar flags permanentes: técnica de "flag debt" e remoção agendada
Crie um arquivo FLAGS_DEBT.md no repositório para rastrear flags que precisam ser removidas.
# FLAGS_DEBT.md
| Flag | Data de Criação | Data Limite | Responsável |
|------|----------------|-------------|-------------|
| nova-busca | 2024-01-15 | 2024-03-15 | @joao |
| dark-mode | 2024-02-01 | 2024-04-01 | @maria |
7.2. Cuidado com conflitos de merge em arquivos de configuração de flags
Use arquivos separados por funcionalidade para evitar conflitos.
config/flags/
├── busca.yaml
├── ui.yaml
└── pagamento.yaml
7.3. Documentação no README do repositório: mapa de flags ativas
# README.md
## Feature Flags Ativas
| Flag | Estado | Descrição | Como Desativar |
|------|--------|-----------|----------------|
| nova-busca | Ativa (50%) | Nova engine de busca | `git revert <commit-hash>` |
| dark-mode | Ativa (100%) | Modo escuro | Remover em 2024-04-01 |
Referências
- Feature Toggles (Martin Fowler) — Artigo seminal que define conceitos, tipos de flags e estratégias de implementação no código.
- Git Feature Flag Workflow (LaunchDarkly) — Guia prático sobre como integrar feature flags com branches e merges no Git.
- How to Use Git with Feature Flags (Split.io) — Tutorial detalhado sobre workflows de Git com flags, incluindo exemplos de commits e tags.
- Git Branching Strategies with Feature Flags (Harness) — Comparação de estratégias de branching (GitFlow, trunk-based) com feature flags.
- Feature Flags in CI/CD Pipelines (GitLab Docs) — Documentação oficial do GitLab sobre implementação de feature flags em pipelines de CI/CD.
- Removing Feature Flags Safely (Martin Fowler) — Guia sobre como e quando remover flags do código, evitando "flag debt".
- Git Bisect with Feature Flags (Atlassian) — Tutorial sobre como usar
git bisectpara encontrar regressões, aplicável a commits de configuração de flags.