← Back to blog

A Faca de Dois Gumes das Feature Flags: Quando Boas Intenções Dão Errado

AI Translated Read in English
2025-07-15 2 min de leitura
tech
feature-flags
javascript
desenvolvimento-de-software
feature-toggles

Sou grande fã de Feature Flags (também chamadas de Feature Toggles). Pra quem não conhece, são basicamente chaves condicionais no código que permitem fazer deploy de uma funcionalidade nova _sem_ liberar ela pros usuários de imediato. Isso viabiliza:

  • Deploys mais seguros (dark launching, canary releases)
  • Testes em produção
  • Kill switches instantâneos pra features com bug
  • Segmentação granular de usuário (por geografia, conta, etc.)

Mas aqui vai o ponto crítico: feature flags brilham quando são de vida curta. São ferramentas táticas, não arquitetura permanente. Infelizmente, já vi times usarem elas sem cuidado — ignorando gestão de ciclo de vida e riscos operacionais. Vamos destrinchar os anti-padrões.

Red Flag 1: Tratar Flags como Configuração Permanente

O Pecado: usar flags pra customizações de cliente de longo prazo (ex.: flag_customer_x_ui_flow). O Custo:

  • Dívida técnica infla conforme flags obsoletas se acumulam
  • Proliferação de flags deixa o código imprevisível (if flag_a && !flag_b && flag_c...)
  • Complexidade de teste explode combinatoriamente

A Correção: → Converter isso em "configurações de comportamento" guardadas no banco. Armazene ajustes tipo customer_x_ui_flow_enabled no seu próprio banco. Benefícios:

  • Propriedade: sem lock-in de fornecedor nem indisponibilidade de terceiros
  • Auditabilidade: rastreie mudanças via logs da própria aplicação
  • Performance: evite chamadas HTTP em tempo de execução pro serviço de flags

Red Flag 2: Ignorar os Modos de Falha de Terceiros

O Pecado: assumir que seu serviço de flags (LaunchDarkly, Split, etc.) vai estar _sempre_ disponível. O Desastre: quando o serviço de flags cai:

  • Aplicações podem quebrar (se o SDK der timeout)
  • Flags assumem valor padrão de forma imprevisível (ex.: desligando _todas_ as features)
  • Usuários enfrentam comportamento inconsistente

A Correção: → Implemente degradação graciosa:

try {
  featureEnabled = await featureFlagClient.getFlag("new-checkout");
} catch (error) {
  // Assume comportamento seguro durante indisponibilidades
  featureEnabled = false;
}

→ Faça cache local do estado das flags pra sobreviver a quedas curtas → Teste cenários de falha (desligue seu serviço de flags no staging!)

Red Flag 3: Flags Imortais

O Pecado: flags que nunca morrem ("isso é código temporário!"). A Consequência:

  • Configuration drift: flags apodrecem conforme os requisitos mudam
  • Riscos de segurança: flags esquecidas expõem features inacabadas
  • Sobrecarga cognitiva: engenheiro novo enfrenta "arqueologia de flag"

Uma Mentalidade Melhor: Na minha empresa anterior, chamávamos elas de "Rollout Flags" — um truque de nomenclatura deliberado:

  1. Flags _precisam_ ter um plano de remoção definido de antemão (ex.: "remover após 90 dias")
  2. Flags eram amarradas a marcos de rollout (não a "features" abstratas):
  • flag_enable_checkout_phase_1 → remover após 95% de rollout
  • flag_migrate_legacy_billing → remover após migração de dados

Isso nos forçou a:

  • Automatizar a limpeza de flags (ex.: CI falha se flag tem mais de 60 dias)
  • Tratar flags como andaime transitório, não como bloco de construção

Minhas Regras de Ouro

  1. Vida Curta > Permanente: flags são como sutura cirúrgica — remova assim que o ferimento cicatrizar.
  2. Dono da Própria Configuração: comportamento específico de cliente? Use seu banco de dados, não um fornecedor de flags.
  3. Planeje pra Falha: o que acontece quando seu serviço de flags explode?
  4. Nomeie com Intenção: "Rollout Flags" > "Feature Flags" (semântica molda comportamento!).

Feature flags são poderosas — mas com grande poder vem grande dívida técnica. Pode com força, projete na defensiva, e mantenha seu jardim de flags arrumado.