O que é feature flag: guia prático para desenvolvimento
Resumo
Feature flags são condicionais que decidem em tempo de execução qual comportamento ativar, sem novo deploy. Elas permitem merge seguro de código inacabado, rollouts graduais e fallback rápido. Mas 75% das flags viram dívida técnica. Este guia cobre os quatro tipos, limpeza eficiente e quando pular flags.
O que é feature flag? É um condicional no seu código que decide em tempo de execução se um comportamento específico está ativado ou desativado, sem novo deploy. Essa é a ideia principal.
Na prática, uma feature flag é uma instrução if cuja resposta vem de uma configuração, uma linha de banco de dados ou um serviço de flags, em vez de estar hardcoded.
O conceito é simples. Viver com 200 delas em um repositório não é, e essa segunda parte é realmente sobre o que este guia trata.
Como é uma feature flag no código?
Aqui está a versão mais simples e útil:
if (flags.isEnabled("new-checkout", { userId })) {
return renderNewCheckout();
}
return renderOldCheckout();Os dois caminhos de código estão no mesmo build. O valor da flag vive em algum lugar que você pode alterar sem fazer redeploy: uma variável de ambiente, um arquivo JSON, uma tabela ou um serviço hospedado. Mude o valor e o comportamento muda na próxima avaliação.
Essa separação é o ponto. Deploy é colocar código nos servidores. Release é deixar os usuários o verem. Flags separam esses dois eventos, então fazer merge para a main não significa mais "todos recebem isso agora".

Por que as equipes usam feature flags?
Três razões aparecem continuamente em equipes reais de 5 a 50 engenheiros.
Fazer merge de trabalho inacabado com segurança. Você commit a feature meio-construída atrás de uma flag desativada, e seu branch nunca fica vivo por três semanas. Isso é o que torna o trunk-based development viável.
Lançar gradualmente. Ative uma mudança para usuários internos, depois 5% do tráfego, depois todos. Se as taxas de erro dispararem, você a desativa em segundos.
Matar algo rápido. Quando um provedor de pagamento misbehaves às 2 da manhã, uma flag permite que o on-call degrade uma feature em vez de fazer rollback de toda uma release.
Nenhuma dessas requer um vendor. Uma flag pode ser um booleano em uma tabela de configuração. Pule a plataforma até precisar de rollouts percentuais, audit trails ou não-engenheiros toggling coisas.
Quais são os quatro tipos de feature flags?
O amplamente citado artigo sobre feature toggles de Pete Hodgson no site de Martin Fowler classifica flags por quanto tempo vivem e com que frequência a decisão muda. As categorias continuam sendo o modelo mental mais claro.
Release: vive dias a semanas, alternada por engenheiros. Exemplo: esconder um redesign de checkout inacabado.
Experiment: vive semanas, alternada por product e data. Exemplo: um teste A/B de duas páginas de pricing.
Ops: vive horas a sempre, alternada por on-call. Exemplo: um kill switch para um serviço de recomendações lento.
Permission: vive meses a anos, alternada por product e support. Exemplo: acesso beta ou features premium.
A coluna de lifespan importa mais. Uma release flag que sobrevive ao seu release é um bug que você ainda não encontrou. Uma permission flag que é deletada em um sprint de cleanup é uma falha que você ainda não teve.
Nomeie e rotule o tipo quando criar a flag. Seis meses depois, ninguém se lembra de qual categoria "new-nav-v2" era.

Como fazer rollout de uma flag sem prejudicar usuários?
A sequência chata funciona melhor.
Coloque o código com a flag desativada. Verifique se nada mudou.
Ative para seu próprio time em produção. Use por um dia.
Ative para 1% a 5% dos usuários, sticky por user ID para que ninguém alterne entre variantes durante a sessão.
Observe taxa de erro, latência e uma métrica de negócio. Decida o threshold antes de começar, não enquanto olha para um dashboard.
Aumente para 100%, espere um período definido, então remova a flag.
A etapa cinco é a que as equipes pulam. Vamos chegar a por que isso custa mais do que você pensa.
Uma nota prática sobre avaliação: faça leitura de flags barata e fail-safe. Se o serviço de flags está down, seu código precisa de um default. Escolha o default por flag, de propósito. Um kill switch deve falhar para "seguro", enquanto uma nova feature deve falhar para "off".
Por que feature flags se tornam dívida técnica?
Cada flag é um fork no seu código. Duas flags fazem quatro caminhos possíveis, dez flags fazem 1.024, e você quase certamente testou um punhado deles. O guia de dívida técnica de flags da GrowthBook cita pesquisas mostrando que cerca de 75% dos componentes de toggle ainda estavam em codebases até 49 semanas após sua introdução, mesmo que a maioria dos desenvolvedores dissesse que planejava removê-los.
Hodgson coloca bem no mesmo artigo de Fowler: equipes experientes tratam toggles como inventário com custo de carregamento, e trabalham para manter esse inventário baixo.
A história clássica de horror é Knight Capital em 2012. Uma flag de feature aposentada foi reutilizada para novo comportamento enquanto código antigo ainda estava em um servidor. Esse descompasso contribuiu para aproximadamente $460 milhões em perdas em menos de uma hora. Sua flag obsoleta provavelmente não fará isso. Ela fará algo mais silencioso: um refactor que quebra um branch que ninguém sabia que existia, ou um novo hire gastando uma tarde descobrindo qual de dois caminhos de checkout é real.

Como você encontra cada flag em um codebase existente?
Essa é a pergunta que os docs do vendor pulam, e é onde a maioria das equipes fica presa. O dashboard de flags diz o que está configurado. Ele não diz onde cada flag é lida no código, ou se o caminho de código atrás de uma flag "off" ainda é alcançável.
Comece com a abordagem barata:
# toda chave de flag literal lida via seu wrapper
rg -n 'isEnabled\("' src/ | sort
# flags definidas mas nunca referenciadas
comm -23 <(jq -r 'keys[]' flags.json | sort) \
<(rg -o 'isEnabled\("([^"]+)"' -r '$1' src/ | sort -u)Isso desmorona rápido. Chaves de flag construídas a partir de concatenação de strings não aparecem em grep. Flags passadas através de funções helper escondem seus call sites. Monorepos e setups multi-repo multiplicam o problema, porque a mesma chave pode ser lida por três serviços.
É aí que ler o código com tooling ajuda. Ferramentas de busca de código que entendem seu repo podem responder "onde new-checkout é avaliado, e o que depende do resultado?" em uma query em vez de uma tarde de grep. Cursor e GitHub Copilot lidam com isso razoavelmente dentro de um repo. Entre vários repos, você precisa de um index que abranja todos eles, que é o caso que construímos codebasechat para.
Como é um processo sane de limpeza de flags?
Trate a remoção como parte do trabalho, não como uma tarefa para depois.
Crie o ticket de remoção com a flag. Linke-o na descrição da flag. Se o ticket não existe, a flag não faz ship.
Defina um owner e uma data de expiração em cada flag não-permanente. Aproximadamente 90 dias sem uma mudança é um trigger razoável para revisão.
Remova em dois pull requests. Primeiro delete o check de flag e mantenha o caminho vencedor. Depois delete o branch morto e seus testes. Diffs pequenos são diffs reviewable.
Adicione um time bomb test. Um teste que falha quando uma release flag passa sua data de expiração transforma uma boa intenção em um build vermelho.
Coloque um cap no total. Se você tem 40 flags ativas e o limite é 40, adicionar uma significa remover uma.
Análise estática ajuda aqui também. Uma ferramenta como CodeScene pode mostrar quais arquivos carregam a lógica condicional mais emaranhada, que é geralmente onde flags antigas se aglomeram. SonarQube marca código inalcançável e morto depois que você remove um check.
Como você testa código que fica atrás de uma flag?
Testes são a parte que ninguém orça. Com dois caminhos por flag, sua suite de testes precisa cobrir ambos, pelo menos para as flags que guardam comportamento arriscado.
Mantenha prático. Teste os estados on e off de cada release flag em testes unitários, injetando o valor da flag em vez de ler um serviço ao vivo. Execute uma suite end-to-end contra a configuração de produção padrão, porque é isso que os usuários recebem hoje. Depois execute um segundo passe com a flag on para a feature que você está prestes a lançar.
Não tente testar cada combinação. Com dez flags você não consegue. Em vez disso, mantenha flags independentes: uma flag que muda comportamento apenas quando outra flag também está on é um design smell, e é a primeira coisa a desemaranhar.
O que novos engenheiros entendem mal sobre flags?
Juniores tendem a cometer os mesmos três erros, e cada um é barato de prevenir em review.
Aninhamento de flags. Uma flag dentro de outra cria um caminho que existe apenas quando ambas estão on. Peça uma única flag com um nome claro em vez disso.
Colocar lógica no nome da flag. Uma chave como "show-new-nav-to-premium-users-in-eu" codifica uma regra de targeting que pertence ao serviço de flags, não a uma string.
Esquecer o default. Se o lookup de flag falha, o que acontece? Faça o author escrever a resposta na descrição do pull request.
As duas primeiras semanas de um novo hire são exatamente quando eles encontram flags antigas sem owner. Um registro de flags curto, com um tipo, um owner e uma data de remoção para cada entrada, economiza várias horas de perguntar por aí.
Quando você deve pular feature flags?
Flags não são gratuitas, então pule-as quando:
A mudança é pequena, reversível e um deploy afastada de um rollback. Uma flag adiciona um caminho de código sem ganho.
A mudança toca um schema de banco de dados de uma forma que uma flag não consegue esconder. Use expand-and-contract migrations em vez disso.
Seu time não tem processo para remover flags. Corrija isso primeiro, ou você está tomando emprestado da legibilidade futura.
E use-as sem hesitação quando uma mudança é arriscada, voltada para o usuário e difícil de reverter redeploy. Fluxos de pagamento, mudanças de auth e qualquer coisa com uma migração de dados atrás dela se qualificam.
O que realmente faríamos em um time de dez
Comece com um booleano em config e uma função wrapper única, para que cada leitura de flag passe por um lugar. Esse ponto único de estrangulamento torna a lista de flags greppable, auditável e fácil de migrar para um serviço hospedado depois.
Rotule cada flag por tipo, dê a ela um owner e abra o ticket de remoção no dia um. Revise a lista mensalmente por dez minutos. Delete as flags que estão em 100% por duas semanas.
Uma feature flag é um empréstimo. Pegue-a quando economizar um release arriscado, e a pague antes que os juros apareçam no seu próximo refactor.