Feature Flags: O Guia Técnico para Desacoplar Deploy de Release
Entenda como implementar Feature Flags na prática para realizar deploys seguros, mitigar riscos com Kill Switches e gerenciar o ciclo de vida das flags para evitar a dívida técnica no seu código.
A sexta-feira à tarde costuma ser um período de tensão para equipes de engenharia de software. O receio de que um deploy de última hora introduza um bug crítico e arruíne o fim de semana é um sentimento comum. No entanto, essa ansiedade geralmente decorre de um acoplamento desnecessário entre duas etapas distintas do ciclo de entrega: colocar o código em produção e disponibilizar a funcionalidade para o usuário.
As Feature Flags (também conhecidas como Feature Toggles ou Feature Switches) surgem como uma decisão arquitetural prática para resolver esse problema. Ao separar o ato técnico de subir o código do ato de negócio de liberar o recurso, as equipes ganham controle granular sobre o comportamento do sistema em tempo de execução, reduzindo drasticamente o risco operacional.
O que são Feature Flags e a diferença crucial entre Deploy e Release
Para compreender o valor das Feature Flags, é fundamental estabelecer a distinção conceitual entre dois termos frequentemente confundidos:
- Deploy (Implantação): É um evento estritamente técnico e de infraestrutura. Significa transferir o código compilado ou empacotado para os servidores de produção, onde o processo passa a rodar. O código está lá, mas não precisa estar ativo ou visível.
- Release (Lançamento): É um evento de negócio. Significa tornar a funcionalidade acessível e utilizável para os usuários finais (ou para um subconjunto deles).
Sem Feature Flags, deploy e release acontecem simultaneamente. Se você envia um novo fluxo de checkout para a produção, ele entra no ar imediatamente para todos. Se houver um bug, a única saída é realizar um rollback de infraestrutura ou correr contra o tempo com um hotfix.
Com as Feature Flags, o código do novo checkout é implantado desativado. Ele reside em produção, mas permanece inativo até que uma decisão de negócio ou técnica altere o estado da flag. Conforme documentado por referências de engenharia como a LaunchDarkly, essa abordagem mitiga riscos ao permitir que o código seja testado no ambiente real antes de ser exposto ao público geral.
Como as Feature Flags funcionam na prática: Do If/Else aos SDKs
Em sua essência mais simples, uma Feature Flag é uma condicional no código. No entanto, a forma como essa condicional é avaliada evolui conforme a maturidade do projeto.
A evolução técnica
- Condicionais Hardcoded / Variáveis de Ambiente: O nível mais básico utiliza variáveis no arquivo
.envou configurações estáticas. Para alterar o estado da flag, é necessário reiniciar o processo ou realizar um novo deploy de configuração. - Banco de Dados / Redis: O estado da flag é lido de um banco de dados relacional ou de um cache em memória. Permite alteração em tempo real, mas introduz latência de rede a cada verificação e pode sobrecarregar o banco.
- SDKs e Gerenciadores Externos: Utilizam um modelo híbrido. As regras de decisão são gerenciadas externamente, mas o SDK local na aplicação baixa essas regras e as avalia em memória, garantindo latência próxima de zero e atualizações em tempo real via streaming (como Server-Sent Events).
Exemplo prático de código (TypeScript)
Abaixo, demonstramos a implementação de uma verificação de flag para um novo fluxo de checkout, utilizando um contexto de usuário para permitir liberação segmentada:
interface UserContext {
id: string;
email: string;
tier: 'free' | 'premium';
}
class FeatureFlagService {
// Em um cenário real, este método consumiria um SDK local ou cache em memória
async isEnabled(flagName: string, context: UserContext): Promise<boolean> {
if (flagName === 'new-checkout-flow') {
// Regra: Liberar apenas para usuários Premium ou emails específicos para teste interno
return context.tier === 'premium' || context.email.endsWith('@loopino.com.br');
}
return false;
}
}
// Exemplo de uso no Controller de Checkout
async function handleCheckout(req: any, res: any) {
const user: UserContext = req.user;
const flagService = new FeatureFlagService();
const useNewCheckout = await flagService.isEnabled('new-checkout-flow', user);
if (useNewCheckout) {
// Executa a nova lógica de checkout refatorada
return renderNewCheckout(req, res);
} else {
// Mantém o fluxo legado estável
return renderLegacyCheckout(req, res);
}
}
Estratégias de Lançamento: Canary Releases, Testes A/B e o Poder do Kill Switch
Ao adotar Feature Flags, a equipe de engenharia desbloqueia uma série de estratégias avançadas de entrega contínua:
Canary Releases
Em vez de liberar uma funcionalidade para 100% da base de usuários, você a ativa para apenas 1%. O SDK calcula um hash baseado no ID do usuário para garantir que o mesmo usuário sempre tenha a mesma experiência (consistência de sessão). Se as métricas de erro e performance da aplicação permanecerem estáveis, o percentual é elevado gradualmente (5%, 25%, 50%, 100%).
Testes A/B
As flags podem atuar como direcionadoras de tráfego para experimentos. Metade dos usuários passa pelo fluxo “A” (controle) e a outra metade pelo fluxo “B” (variante). Integrando esses dados com ferramentas de analytics, a equipe de produto consegue validar hipóteses de conversão com dados reais.
Dark Launches
Consiste em enviar tráfego real para um novo serviço de backend sem que o usuário perceba na interface. Por exemplo, ao refatorar uma API de busca, a interface continua exibindo os resultados da API antiga, mas uma Feature Flag faz uma chamada em background para a nova API apenas para comparar a performance e a precisão dos resultados sob carga real.
O Kill Switch (Botão de Emergência)
Se um bug crítico passar despercebido pelos testes e chegar a produção, o desenvolvedor ou a equipe de operações não precisa realizar um rollback complexo ou aplicar um hotfix às pressas. Basta desativar a flag no painel administrativo. O tráfego é redirecionado instantaneamente para o código legado estável, minimizando o tempo de indisponibilidade (MTTR).
Essa dinâmica de controle em produção acelera a evolução do papel do QA, que deixa de ser um mero homologador pré-deploy para atuar como um engenheiro de qualidade focado em estratégias de testes em produção e resiliência de sistemas.
Integração no Pipeline de CI/CD e Testes Automatizados
Para que as Feature Flags funcionem de forma confiável, elas precisam estar integradas ao fluxo de integração e entrega contínua.
Ao implementar pipelines de CI/CD, a automação deve garantir que o código seja testado sob diferentes cenários. Um erro comum é testar a aplicação apenas com as flags em seu estado padrão (geralmente desligadas). Se o novo código contiver erros de sintaxe ou incompatibilidades de dependências, o pipeline passará, mas a aplicação quebrará quando a flag for ativada em produção.
Por isso, é crucial integrar testes automatizados no pipeline configurando matrizes de teste (test matrices). Os testes de integração e ponta a ponta (E2E) devem rodar em duas passagens:
- Passagem A: Todas as flags de release ativas.
- Passagem B: Todas as flags de release inativas.
Essa abordagem garante a consistência dos testes automatizados e previne regressões em ambos os caminhos de execução do código.
O Calcanhar de Aquiles: Gerenciamento do Ciclo de Vida e Dívida Técnica
Embora tragam flexibilidade, as Feature Flags introduzem complexidade cognitiva e caminhos alternativos de execução. Se não forem gerenciadas com rigor, o código se tornará um emaranhado de condicionais obsoletas, gerando uma grave dívida técnica.
Cenário Real: Refatoração de Banco de Dados (Expand and Contract)
Imagine uma migração onde a tabela usuarios precisa ter o campo nome_completo dividido em primeiro_nome e sobrenome. Usando Feature Flags, aplicamos o padrão Expand and Contract:
- Expandir: Adicionamos as novas colunas ao banco de dados. O código antigo continua lendo de
nome_completo. O novo código (atrás de uma flag) escreve em ambos os campos para manter a paridade. - Migrar: Rodamos um script para migrar os dados históricos.
- Contrair: Ativamos a flag para ler apenas das novas colunas. Após validar a estabilidade, removemos a flag, o código antigo e, finalmente, a coluna antiga do banco.
Se a equipe esquecer de realizar o passo de “Contrair”, o sistema continuará executando lógicas redundantes de escrita e leitura por anos.
Boas práticas de governança para evitar código morto
Para mitigar esse acúmulo, adote as seguintes diretrizes:
- Classifique as Flags: Separe as flags em temporárias (flags de release, que devem durar semanas) e permanentes (flags operacionais, como limites de taxa de API ou modo de manutenção).
- Defina Proprietários (Owners): Toda flag deve ter um desenvolvedor ou time responsável por sua remoção.
- Agende o Cleanup no Backlog: Assim que uma funcionalidade atinge 100% de liberação e estabilidade, uma tarefa de remoção da flag e do código legado correspondente deve ser priorizada na sprint seguinte.
- Alertas de Obsolescência: Configure ferramentas ou scripts para alertar quando uma flag estiver ativa em 100% do tráfego por mais de 14 dias sem sofrer alterações.
Ferramentas de Feature Flags: Comparativo entre Open Source e SaaS
A escolha da ferramenta ideal depende de fatores como orçamento, requisitos de conformidade de dados (como LGPD/GDPR) e volume de requisições.
| Ferramenta | Modelo | Principais Prós | Principais Contras | Caso de Uso Ideal |
|---|---|---|---|---|
| LaunchDarkly | SaaS | Plataforma extremamente madura, segmentação ultra-granular, excelente suporte corporativo. | Custo elevado para equipes pequenas; dependência de infraestrutura externa. | Grandes empresas com fluxos complexos de produto e múltiplos times. |
| Unleash | Open Source / SaaS | Excelente controle de privacidade (versão self-hosted mantém dados na sua infraestrutura). | Requer gerenciamento de infraestrutura própria na versão gratuita. | Empresas com regras estritas de conformidade e segurança de dados. |
| Flagsmith | Open Source / SaaS | Interface simples, fácil de integrar, permite self-hosting completo sem limitações severas. | Menos recursos nativos de experimentação avançada em comparação ao LaunchDarkly. | Equipes de médio porte que buscam equilíbrio entre custo e controle. |
| GrowthBook | Open Source / SaaS | Foco nativo em experimentação e testes A/B, integra-se diretamente com seus data warehouses. | Configuração inicial de analytics pode ser complexa. | Times focados em Growth e Product Analytics que já possuem infraestrutura de dados. |
| PostHog | SaaS / Open Source | Plataforma unificada (combina flags, session recording, heatmaps e analytics). | Pode ser excessivo se você precisa apenas de gerenciamento de flags. | Startups que desejam uma única ferramenta para entender o comportamento do usuário. |
Conclusão
Feature Flags não são apenas uma ferramenta técnica, mas uma mudança cultural na forma como o software é concebido, testado e entregue. Elas reduzem o estresse dos deploys, aproximam a engenharia dos objetivos de negócio e permitem que falhas sejam contidas em segundos.
No entanto, o sucesso dessa prática exige disciplina. Trate cada flag temporária como um empréstimo técnico: use-a para mitigar o risco do lançamento, mas pague a dívida removendo-a do código assim que o objetivo for alcançado.
Perguntas Frequentes (FAQ)
O uso de Feature Flags afeta a performance da aplicação?
Em geral, não. Os SDKs modernos de ferramentas como Unleash e Flagsmith não fazem requisições HTTP síncronas a cada verificação de flag. Eles baixam as regras de direcionamento em background e as avaliam localmente em memória. O impacto na latência é insignificante (frequentemente inferior a 1 milissegundo).
Como lidar com migrações de banco de dados usando Feature Flags?
A recomendação é utilizar o padrão Expand and Contract. O banco de dados deve ser alterado de forma incremental para suportar tanto o código antigo quanto o novo simultaneamente. A Feature Flag controla a transição lógica da aplicação. Somente após a flag ser consolidada e o código antigo removido é que a estrutura antiga do banco de dados é eliminada.
Qual é o tempo de vida ideal de uma Feature Flag de release?
Flags de release devem ser estritamente temporárias. O ciclo de vida ideal varia de duas a quatro semanas. Manter uma flag ativa por meses após o lançamento completo aumenta a complexidade de testes e dificulta a onboarding de novos desenvolvedores na base de código.
Referências
- Martin Fowler on Feature Toggles: martinfowler.com/articles/feature-toggles.html
- LaunchDarkly Guide to Decoupling Deploy and Release: launchdarkly.com
- Octopus Deploy: Types of Feature Flags and Best Practices: octopus.com
Sobre Marcos Costa
Desenvolvedor backend com foco em arquitetura de software, automação e produtos digitais.
Ver mais artigos