Feature Flag: Como Implementar sem Virar Bagunça no Código
O que é feature flag
Feature flag é uma condicional que decide, em tempo de execução, se um trecho de código
fica ativo ou não, sem exigir um novo deploy para mudar essa decisão. Em vez de um
if fixo resolvido no momento da compilação, a flag consulta uma configuração externa
que pode mudar a qualquer momento.
Na prática, o código fica assim: if (flags.novoCheckout) { ... } else { ... }. O que
muda de um sistema simples para um maduro é onde flags.novoCheckout busca esse valor.
Um projeto pequeno lê de uma variável de ambiente. Um sistema com múltiplas equipes lê de
um serviço dedicado que permite ligar a flag para uma fatia pequena dos usuários sem
tocar em código.
Por que feature flag substitui branch de longa duração
Uma branch de feature que vive semanas acumula conflito de merge a cada dia que passa, porque o resto do time continua integrando código na branch principal enquanto a sua fica parada. Feature flag resolve isso ao permitir que o código incompleto entre na branch principal cedo, escondido atrás de uma condicional desligada.
O time integra o trabalho todo dia, roda os testes de todo mundo contra o código de todo mundo, e só decide quando a funcionalidade fica visível depois, ligando a flag. Isso separa duas decisões que costumavam estar amarradas: quando o código entra no repositório e quando o usuário vê a mudança. São perguntas diferentes, com respostas diferentes.
Quais tipos de feature flag existem
Os quatro tipos mais comuns resolvem problemas distintos, e confundir um pelo outro é o erro mais frequente em quem começa a usar flag.
Release toggle controla o lançamento gradual de uma funcionalidade nova, geralmente removida do código algumas semanas depois que a funcionalidade vira padrão para todo mundo. É a flag de vida mais curta.
Ops toggle, também chamada de kill switch, existe para desligar rapidamente uma funcionalidade que está causando problema em produção, sem precisar de um deploy de emergência. Um exemplo hipotético: uma integração com um provedor de pagamento externo começa a responder devagar, e o time desliga a chamada por trás de uma ops toggle enquanto investiga, mantendo o resto do checkout funcionando.
Permission toggle libera uma funcionalidade só para um grupo específico de usuários, como clientes de um plano pago ou uma lista de testadores internos. Ao contrário das duas anteriores, ela costuma viver no sistema de forma permanente.
Experiment toggle divide o tráfego entre duas versões para comparar métrica, o componente técnico por trás de um teste A/B. Assim como a release toggle, tem vida curta: o experimento termina, a versão vencedora vira a única, e a flag some.
Onde guardar o estado de cada flag
Onde a flag mora determina o quanto ela custa para operar e o quanto ela permite granularidade na hora de ligar.
Um arquivo de configuração ou variável de ambiente resolve para poucas flags que mudam raramente: é a opção mais simples, mas exige deploy para alterar o valor, o que contradiz parte do motivo de usar flag em primeiro lugar. Um registro em banco de dados já permite mudar o valor sem deploy, lido pela aplicação a cada requisição ou em cache com expiração curta.
Serviços dedicados, como Unleash na versão open source ou plataformas comerciais como LaunchDarkly, adicionam o que configuração simples não oferece: liberar para uma porcentagem do tráfego, segmentar por atributo do usuário e manter histórico de quem mudou o quê. Para times pequenos, um registro em banco com uma tabela de flags e um cache de poucos segundos já cobre a maior parte do caso de uso, na mesma linha do que discutimos em cache de aplicação para outros tipos de dado que mudam pouco e são lidos muito.
Como implementar feature flag num sistema em produção
Introduzir flag num sistema que nunca usou exige alguns cuidados para não criar mais confusão do que a que já existia.
- Comece por um caso de uso concreto, de preferência um kill switch para uma integração externa instável. É o tipo que mostra valor mais rápido.
- Escolha um nome de flag que descreva o comportamento, não a data ou o ticket, como
checkoutV2em vez deflagSprint14. O nome sobrevive ao contexto que o originou. - Centralize a leitura da flag numa função ou módulo único. Espalhar a chamada ao provedor de flag pelo código inteiro torna a remoção, mais tarde, muito mais difícil.
- Defina, já na criação da flag, um valor padrão seguro para quando o serviço que guarda o estado estiver indisponível. A aplicação não pode quebrar porque o serviço de flag caiu.
- Registre a data de criação da flag e o tipo dela. Uma release toggle sem data de criação é a semente da próxima seção deste artigo.
- Cubra os dois caminhos da condicional com teste automatizado, seguindo o que já vale para qualquer branch de código em testes automatizados: o caminho não testado é o que quebra em produção.
Como evitar acumular flag morta no código
Flag morta é toda condicional cujo resultado já foi decidido há meses, mas que continua
no código como um if que só um caminho jamais executa. Ela não trava o sistema
sozinha, mas empilha complexidade cognitiva sem entregar valor nenhum.
O jeito mais direto de evitar isso é tratar a remoção da flag como parte da definição de pronto da funcionalidade, não como uma tarefa futura que alguém vai lembrar de fazer. Quando a release toggle chega a 100% dos usuários e fica estável por um tempo razoável, remover a condicional e o caminho morto é trabalho do mesmo ciclo, não um débito adiado. Esse é o mesmo raciocínio de priorização que vale para qualquer débito técnico: quanto mais tempo a flag morta fica no código, mais caro fica removê-la, porque outras mudanças vão se acumulando em cima dela.
Uma auditoria trimestral simples ajuda: liste as flags ativas, marque a data de criação de cada uma e pergunte, para toda release toggle com mais de alguns meses, por que ela ainda existe. Na maioria das vezes a resposta é que ninguém teve tempo de remover, não que ela ainda é necessária.
Feature flag entrega o que promete quando o time trata cada flag como algo com início e fim previstos, não como uma configuração que fica lá para sempre por segurança. Se o seu deploy ainda depende de tudo estar pronto ao mesmo tempo, fale com a gente para desenhar uma esteira de entrega mais gradual.