Imagine o seguinte cenário: seu time está trabalhando em uma feature complexa que vai levar três semanas para ficar pronta. O instinto natural e criar um feature branch, trabalhar nele durante essas três semanas e depois fazer um mega-merge de volta para o branch principal. O problema e que, quando o merge finalmente acontece, ele traz conflitos, bugs de integração e uma quantidade enorme de código para revisar de uma so vez. Esse padrão e tao comum quanto problematico.
Feature flags oferecem uma alternativa elegante: você faz deploy do código novo diáriamente no branch principal, mas escondido atras de uma flag que controla quem pode ve-lo. O código vai para produção incrementalmente, mas a featuré só e "ligada" quando está completa e validada. Issó separa completamente o conceito de deploy (colocar código em produção) do conceito de release (disponibilizar a feature para usuários).
O que são feature flags
Feature flags (também chamadas de feature toggles, feature switches ou feature gates) são mecanismos que permitem ativar ou desativar funcionalidades em tempo de execução, sem necessidade de um novo deploy. Na sua forma mais básica, uma feature flag e um condicional no código:
Mas feature flags modernas vao muito além de um simples if/else. Elas permitem segmentação avançada: ativar a feature apenas para usuários internos, para 10% dos usuários, para usuários de uma regiao específica ou para usuários que optaram por participar de um programa beta. Tudo isso controlado por um painel de administração ou API, sem tocar no código.
"Feature flags transformam o deploy de um evento binario (tudo ou nada) em um dial que você pode girar gradualmente, com a capacidade de voltar a zero instantaneamente se algo der errado."
Por que branches longas são problematicas
Para entender o valor das feature flags, é importante entender por que a alternativa tradicional, branches longas, causa tantos problemas:
Merge hell
Quanto mais tempo um branch vive separado do trunk, mais diverge dele. Quando chega a hora do merge, os conflitos se multiplicam. Resolver conflitos de merge complexos e tedioso, propenso a erros e frequentemente introduz bugs sutis qué só aparecem em produção.
Code reviews impossíveis
Um PR com 5.000 linhas modificadas e, na prática, impossível de revisar com qualidade. Estudos mostram que a eficácia do code review cai drasticamente após 200-400 linhas. Branches longas acumulam mudanças que resultam em PRs enormes que recebem um "LGTM" superficial.
Feedback tardio
Se o código so e integrado após semanas, problemas de integração, performance e usabilidadé só são descobertos no final. Feedback tardio e caro: corrigir um problema de design quando o código já está "pronto" e ordens de magnitude mais caro do que corrigi-lo no início.
Risco concentrado
Um mega-merge concentra todo o risco em um único momento. Se algo da errado, é difícil identificar qual das muitas mudanças causou o problema. Com integração continua via feature flags, cada mudança é pequena e isolada, fácilitando a identificação e correção de problemas.
Tipos de feature flags
Nem todas as feature flags são iguais. Martin Fowler e Pete Hodgson categorizam as flags em quatro tipos, cada um com características e ciclo de vida diferentes:
Release flags
O tipo mais comum. Permitem que código incompleto seja mergeado no trunk sem afetar usuários. São temporarias: devem ser removidas assim que a feature está totalmente lancada. Ciclo de vida típico: dias a semanas.
Experiment flags
Usadas para testes A/B e experimentação. Direcionam diferentes grupos de usuários para diferentes variações de uma feature para medir qual performa melhor. São temporarias, mas geralmente vivem mais que release flags. Ciclo de vida típico: semanas a meses.
Ops flags
Usadas para controlar aspectos operacionais do sistema. Um circuit breaker que desativa uma funcionalidade quando um serviço dependente está instável, por exemplo. Podem ser permanentes ou semi-permanentes. São acionadas em resposta a condições do sistema, não decisões de produto.
Permission flags
Controlam acesso a funcionalidades baseado em características do usuário: plano de assinatura, papel, localização. São geralmente permanentes e fazem parte da lógica de negócio do produto.
Implementando feature flags na prática
Abordagem simples: configuração baseada em arquivo
Para times que estão começando, uma abordagem simples com um arquivo de configuração pode ser suficiente. Um arquivo JSON ou YAML com as flags e seus estados, lido pela aplicação na inicialização. Mudanças requerem um deploy, mas o custo de implementação é mínimo.
Essa abordagem funciona para release flags básicas, mas tem limitações: não permite segmentação de usuários, não permite mudanças em tempo real e não oferece auditoria de quem mudou o que.
Abordagem intermediária: banco de dados + painel admin
O próximo nível e armazenar flags em um banco de dados com um painel de administração para gerencia-las. Isso permite mudanças em tempo real sem deploy e adiciona básica de auditoria. A aplicação consulta o banco (com cache adequado) para avaliar as flags.
Essa abordagem atende a maioria dos casos de uso, mas requer desenvolvimento e manutenção do painel e da lógica de avaliação. E um bom ponto de equilibrio entre simplicidade e funcionalidade.
Abordagem avançada: plataforma dedicada
Para times que fazem uso intensivo de feature flags, plataformas dedicadas oferecem funcionalidades avançadas:
- LaunchDarkly: A plataforma mais madura e completa, com SDKs para todas as linguagens, segmentação avançada, testes A/B e integração com ferramentas de observabilidade.
- Unleash: Alternativa open-source ao LaunchDarkly, com funcionalidades sólidas e possibilidade de self-hosting.
- Flagsmith: Outra opção open-source com bom equilibrio entre funcionalidades e simplicidade.
- Split.io: Focada em experimentação e feature delivery, com análise de impacto integrada.
Estratégias de rollout com feature flags
Uma das maiores vantagens das feature flags e a flexibilidade no rollout de novas funcionalidades. Aqui estão as estratégias mais comuns:
Rollout interno (dogfooding)
Ative a feature primeiro para funcionarios da empresa. Isso permite que bugs e problemas de usabilidade sejam detectados em um ambiente controlado, por pessoas que entendem o contexto e podem dar feedback detalhado.
Rollout por porcentagem
Aumente gradualmente a porcentagem de usuários que veem a feature: 1%, 5%, 10%, 25%, 50%, 100%. Em cada etapa, monitore métricas de saude (taxa de erro, latencia, conversão) é só avance se tudo estiver saudável. Se detectar problemas, volte para a porcentagem anterior ou desative completamente.
Rollout por segmento
Ative para segmentos específicos de usuários: usuários premium, usuários de um pais específico, usuários que optaram pelo beta. Isso permite validar a feature com um público relevante antes do lançamento geral.
Rollout por anel (ring deployment)
Uma combinação das abordagens acima em aneis concentricos: primeiro o time interno, depois beta testers, depois usuários premium, depois 10% dos usuários gerais, e finalmente todos. Cada anel serve como uma camada de validação.
Feature flags e trunk-based development
Feature flags são o que torna trunk-based development viavel para features complexas. O fluxo funciona assim:
- Crie a feature flag antes de começar o desenvolvimento
- Desenvolva a feature em pequenos commits no trunk, sempre atras da flag
- Cada commit e deployado em produção automaticamente, mas a feature está desativada
- Faca code reviews de PRs pequenos (50-200 linhas), que são fáceis de revisar e entender
- Quando a feature está completa, ative a flag para o time interno para dogfooding
- Faca o rollout gradual conforme descrito acima
- Quando a feature está 100% lancada e estável, remova a flag e o código condicional
Esse fluxo elimina branches longas, mega-merges e code reviews impossíveis. Cada passo é pequeno, reversível e controlado.
Gerenciando a dívida técnica de feature flags
Feature flags são poderosas, mas criam dívida técnica se não forem gerenciadas. Flags antigas que nunca foram removidas adicionam complexidade ao código: condicionais extras, caminhos de execução adicionais e cognitiva overhead para quem le o código.
Politica de limpeza
Estabeleca uma politica clara para remoção de flags:
- Release flags: Devem ser removidas dentro de duas semanas após o rollout completo (100% dos usuários).
- Experiment flags: Devem ser removidas dentro de uma semana após a conclusão do experimento e a decisão sobre qual variação manter.
- Ops flags: Revisar trimestralmente. Se uma ops flag nunca foi usada em três meses, considere remove-la.
- Permission flags: Revisar anualmente como parte da revisão do modelo de permissões.
Automação de limpeza
Automatize a detecção de flags obsoletas. Ferramentas podem analisar o código e identificar flags que foram completamente ativadas (sempre retornam true) ou que não foram avaliadas em semanas. Crie alertas ou tarefas automáticas no seu board quando uma flag ultrapassa seu prazo de validade.
Limite de flags ativas
Defina um limite máximo de flags ativas simultaneamente. Quando o limite e atingido, o time deve remover flags antigas antes de criar novas. Isso cria um incentivo natural para limpeza.
Observabilidade e feature flags
Feature flags adicionam uma dimensao importante a observabilidade. Quando algo da errado em produção, você precisa saber não apenas que métricas degradaram, mas quais flags estão ativas para os usuários afetados.
- Inclua flags nos logs: Cada log deve incluir as flags ativas para aquele request. Isso permite filtrar logs por variação da flag.
- Dashboards por flag: Crie dashboards que comparam métricas entre usuários com a flag ativada e desativada. Isso permite detectar rapidamente se uma flag específica está causando problemas.
- Correlacione deploys e flag changes: No timeline de eventos, registre tanto deploys quanto mudanças de estado de flags. Frequentemente, a causa de uma degradação não e um deploy, mas uma flag que foi ativada.
- Kill switch rápido: Garanta que qualquer membro do time pode desativar uma flag problematica em menos de um minuto, sem necessidade de aprovação ou deploy.
Feature flags e testes
Feature flags complicam os testes porque adicionam combinações. Se você tem 10 flags binarias, existem teoricamente 1024 combinações possíveis. Testar todas e imprático. Estratégias para lidar com isso:
- Teste os extremos: Teste com todas as flags ativadas e com todas desativadas. Isso cobre os dois cenários mais comuns.
- Teste combinações relevantes: Identifique flags que interagem entre si e teste essas combinações específicas.
- Testes parametrizados: Escreva testes que rodam com a flag ativada e desativada, verificando o comportamento correto em ambos os casos.
- Monitoring em produção: Use o rollout gradual como seu teste final. Monitoring robusto em produção detecta problemas que testes automatizados podem não cobrir.
Feature flags e gestão de projetos
Feature flags impactam como você planeja e rastreia trabalho. Algumas práticas para integrar flags ao seu fluxo de gestão:
- Cada feature flag deve ter um card correspondente no board, incluindo critérios para rollout e remoção
- O status da flag (criada, em desenvolvimento, dogfooding, rollout parcial, 100%, removida) pode ser rastreado como etapas do card
- O GalagoWork permite vincular flags a PRs e commits via integração GitHub, criando uma trilha completa da feature desde o planejamento até o lançamento
- Relatórios de flags ativas e seus estados ajudam Product Managers a entender o que está em pipeline e o que já está disponível para usuários
Conclusão: deploy não deveria ser sinônimo de risco
Feature flags representam uma mudança fundamental na forma como pensamos sobre deploy e release. Ao separar esses dois conceitos, eliminamos a necessidade de branches longas, reduzimos o risco de cada deploy e ganhamos controle granular sobre quem ve o que em produção.
O investimento inicial em feature flags se paga rapidamente em deploys mais seguros, code reviews mais eficazes, feedback mais rápido e a capacidade de reverter qualquer mudança instantaneamente. E a combinação perfeita entre velocidade é segurança que todo time de engenharia busca.
Comece simples: na próxima feature que seu time iniciar, crie uma feature flag antes do primeiro commit. Desenvolva atras da flag, faca deploy diáriamente no trunk e ative gradualmente quando estiver pronto. Você vai se perguntar como vivia sem isso.