Estratégias de feature flags para releases contínuos

1. Fundamentos de Feature Flags em Releases Contínuos

1.1. Definição e propósito: separação entre deploy e release

Feature flags (também chamadas de feature toggles) são mecanismos de configuração que permitem ativar ou desativar funcionalidades em tempo de execução, sem necessidade de novo deploy. A principal vantagem é separar o momento do deploy (quando o código vai para produção) do momento da release (quando a funcionalidade fica disponível para os usuários). Isso reduz drasticamente o risco de releases, pois o código pode ser implantado continuamente, enquanto a exposição é controlada por flags.

1.2. Ciclo de vida de uma feature flag

Uma feature flag passa por quatro estágios:
- Criação: definição da flag no sistema de gerenciamento
- Ativação: liberação para um subconjunto de usuários
- Desativação: remoção da exposição em caso de problemas
- Remoção: exclusão do código da flag após estabilização

1.3. Diferença entre flags de release, experimentação e operacionais

  • Flags de release: controlam lançamento de novas funcionalidades
  • Flags de experimentação: usadas em testes A/B para medir impacto
  • Flags operacionais: controlam comportamento do sistema (ex: ativar/desativar cache)

2. Tipos de Feature Flags e Casos de Uso

2.1. Flags booleanas simples

São as mais básicas: ativam ou desativam uma funcionalidade para todos os usuários.

// Exemplo de flag booleana em JSON
{
  "feature_flags": {
    "novo_checkout": true,
    "dark_mode": false
  }
}

2.2. Flags percentuais para rollout gradual

Permitem liberar gradualmente uma funcionalidade para uma porcentagem dos usuários. É a base para canary releases.

// Configuração de rollout percentual
{
  "feature_flags": {
    "recomendacao_ia": {
      "enabled": true,
      "rollout_percentage": 10,
      "start_time": "2024-01-15T10:00:00Z"
    }
  }
}

2.3. Flags baseadas em segmentação

Permitem liberar funcionalidades para grupos específicos: por ID de usuário, plano de assinatura, geografia, dispositivo, etc.

// Exemplo de flag segmentada
{
  "feature_flags": {
    "upload_4k": {
      "enabled": true,
      "segments": {
        "plans": ["premium", "enterprise"],
        "countries": ["BR", "US", "DE"],
        "user_ids": ["user_123", "user_456"]
      }
    }
  }
}

3. Arquitetura e Infraestrutura de Gerenciamento de Flags

3.1. Armazenamento centralizado vs. distribuído

  • Centralizado: um serviço único gerencia todas as flags (ex: LaunchDarkly, Split.io). Facilita auditoria, mas pode ser ponto único de falha.
  • Distribuído: flags armazenadas em cache local com sincronização periódica (ex: Redis + polling). Mais resiliente, mas com maior latência de atualização.

3.2. Cache e latência

O impacto na experiência do usuário deve ser mínimo. Estratégia recomendada:

// Estratégia de cache com fallback
1. Verificar cache local (memória) - <1ms
2. Se não encontrado, consultar servidor central - 50-200ms
3. Armazenar resultado em cache por 30-60 segundos
4. Em caso de falha, usar valor padrão (false)

3.3. Integração com CI/CD

As flags devem ser gerenciadas como parte do pipeline de deploy. Exemplo de integração com GitHub Actions:

# .github/workflows/deploy.yml
jobs:
  deploy:
    steps:
      - name: Check feature flags before deploy
        run: |
          # Validar se todas as flags em uso estão registradas
          python scripts/validate_flags.py
      - name: Deploy to production
        run: |
          # Deploy com flags desativadas por padrão
          kubectl apply -f k8s/deployment.yaml

4. Estratégias de Rollout Controlado

4.1. Lançamento progressivo

Aumentar gradualmente a exposição ao longo de dias ou semanas:

// Plano de rollout progressivo
Dia 1: 1% dos usuários internos
Dia 2: 5% dos usuários beta
Dia 3: 10% de todos os usuários
Dia 5: 25% dos usuários
Dia 7: 50% dos usuários
Dia 10: 100% dos usuários (se métricas estáveis)

4.2. Kill switch

Mecanismo de desativação remota imediata. Deve ser independente de outras flags e ter prioridade máxima:

// Kill switch global - desativa todas as novas features
{
  "kill_switch": {
    "active": false,
    "reason": "Incidente no sistema de pagamentos",
    "timestamp": "2024-01-20T14:30:00Z",
    "affected_flags": ["novo_checkout", "recomendacao_ia"]
  }
}

4.3. Dark launch

Testar funcionalidades em produção sem impacto visível para o usuário. O código executa, mas a saída não é exibida:

// Exemplo de dark launch
if (flagService.isEnabled("recomendacao_ia")) {
    // Executa lógica, mas não exibe resultado
    const recomendacoes = await getRecomendacoesIA(userId);
    if (flagService.isVisible("recomendacao_ia")) {
        renderRecomendacoes(recomendacoes);
    }
    // Log para análise de desempenho
    logger.info("Dark launch executado", { userId, recomendacoes });
}

5. Boas Práticas de Gestão do Ciclo de Vida das Flags

5.1. Nomenclatura padronizada

Use prefixos para identificar o tipo e escopo da flag:

// Padrão de nomenclatura
release_<feature_name>      // Flags de release
exp_<experiment_name>       // Flags de experimentação
ops_<operational_name>      // Flags operacionais
kill_<critical_feature>     // Kill switches específicos

5.2. Processo de revisão e aprovação

Toda flag deve passar por revisão de código e aprovação antes de ser criada ou removida:

// Checklist de revisão de flag
1. A flag tem documentação clara?
2. O código da flag será removido em até 30 dias?
3. Existe fallback para quando a flag estiver desativada?
4. A flag tem monitoramento de métricas associado?
5. O kill switch está configurado para esta flag?

5.3. Limpeza técnica

Flags obsoletas geram débito técnico. Estabeleça uma política de remoção:

// Política de remoção de flags
1. Após 100% de rollout estável por 7 dias: remover código da flag
2. Após 30 dias sem uso: remover configuração da flag
3. Auditoria mensal automatizada para flags não utilizadas
4. Métrica: número de flags ativas deve ser < 50

6. Monitoramento, Observabilidade e Métricas

6.1. Logs e rastreamento

Cada decisão de flag deve ser registrada para debugging:

// Log de decisão de flag
{
  "event": "feature_flag_evaluation",
  "flag_name": "recomendacao_ia",
  "user_id": "user_123",
  "result": true,
  "reason": "user_in_segment",
  "timestamp": "2024-01-20T15:00:00Z",
  "latency_ms": 12
}

6.2. Métricas de impacto

Monitore o impacto de cada flag nas métricas de negócio:

// Métricas por flag
{
  "flag_name": "novo_checkout",
  "metrics": {
    "conversion_rate": 0.85,
    "error_rate": 0.02,
    "avg_latency_ms": 320,
    "abandonment_rate": 0.15
  },
  "comparison": {
    "baseline_conversion_rate": 0.82,
    "baseline_error_rate": 0.01
  }
}

6.3. Alertas automáticos

Configure alertas para comportamentos anômalos:

// Regras de alerta
1. Se error_rate > 5% por 5 minutos: alerta crítico
2. Se latency > 500ms por 10 minutos: alerta de performance
3. Se conversion_rate cair > 10%: alerta de negócio
4. Se flag for alterada fora do horário comercial: alerta de segurança

7. Segurança, Conformidade e Controle de Acesso

7.1. Autenticação e autorização

Apenas usuários autorizados podem alterar flags em produção:

// Níveis de acesso
admin: pode criar, alterar e remover qualquer flag
developer: pode criar e alterar flags, mas não remover
viewer: pode apenas visualizar flags
operator: pode ativar/desativar kill switches

7.2. Auditoria de alterações

Toda alteração deve ser registrada com timestamp e identidade do autor:

// Log de auditoria
{
  "action": "flag_updated",
  "flag_name": "recomendacao_ia",
  "user": "maria.silva@empresa.com",
  "previous_value": { "enabled": false },
  "new_value": { "enabled": true, "rollout_percentage": 10 },
  "timestamp": "2024-01-20T15:30:00Z",
  "ip_address": "192.168.1.100",
  "reason": "Início do rollout gradual"
}

7.3. Tratamento em ambientes regulados

Para conformidade com GDPR, HIPAA e outras regulamentações:

// Configuração para ambientes regulados
{
  "feature_flags": {
    "analytics_personalized": {
      "enabled": false,
      "gdpr_consent_required": true,
      "hipaa_compliant": true,
      "data_retention_days": 90,
      "user_opt_out_available": true
    }
  }
}

Referências