Pular para o conteúdo
9 min de leitura

Feature Flags: Como Separar Deploy de Release e Entregar Sem Medo

Por Equipe Nebular ·

Feature flags desacoplam colocar código em produção de ativá-lo para o usuário. Entenda os tipos de flag, rollout progressivo, kill switch e como não afundar em dívida técnica de flags.

Neste artigo

Existe uma diferença que muda a forma como um time entrega software, e que a maioria descobre tarde demais: deploy e release não são a mesma coisa. Deploy é colocar o código em produção. Release é torná-lo visível e ativo para o usuário. Quando esses dois eventos acontecem juntos — o código sobe e no mesmo instante está no ar para todo mundo — cada deploy é uma aposta de tudo ou nada. É aí que entram as feature flags.

Uma feature flag (ou feature toggle) é um interruptor no código que decide, em tempo de execução, se um trecho de funcionalidade está ativo ou não, sem exigir um novo deploy para mudar. Com ela, você faz o deploy do código desligado, e depois liga a funcionalidade quando quiser, para quem quiser — e desliga na mesma velocidade se algo der errado. Vamos entender os tipos de flag, os padrões de uso e as armadilhas que fazem times bem-intencionados afundarem em dívida técnica.

O conceito central: o interruptor em runtime#

No código, uma flag é uma condição:

``python if flags.is_enabled("novo_checkout", user=usuario): return renderizar_novo_checkout(usuario) return renderizar_checkout_antigo(usuario) ``

O que muda tudo é de onde vem o valor de is_enabled. Ele não é uma constante compilada; é buscado em runtime de um serviço de configuração de flags. Isso significa que você pode alterar o comportamento da aplicação — para todos, para 10% dos usuários, para um cliente específico — sem tocar no código e sem reimplantar. O mesmo artefato em produção passa a se comportar de forma diferente porque a configuração da flag mudou.

Essa separação entre deploy e release é o que destrava várias práticas modernas: integração contínua de verdade (você mescla código incompleto, protegido por flag), rollout progressivo, testes A/B, e a capacidade de desligar uma funcionalidade problemática em segundos.

Os tipos de flag (e por que a distinção importa)#

Nem toda flag é igual. Uma classificação clássica separa quatro tipos por longevidade e dinamismo, e confundi-los é a origem de boa parte da bagunça.

Release toggles#

São flags temporárias que escondem funcionalidade em desenvolvimento. Permitem mesclar código incompleto na branch principal sem expô-lo. Vivem dias ou semanas — o suficiente para a funcionalidade ficar pronta e ser ativada. Devem ser removidas assim que a feature está 100% no ar. São a fonte número um de dívida quando esquecidas.

Experiment toggles#

Dividem usuários em grupos para testes A/B. Um grupo vê a variante A, outro a B, e você mede qual converte melhor. São dinâmicas por usuário e vivem o tempo do experimento. A decisão de qual variante cada usuário vê precisa ser consistente (o mesmo usuário sempre cai no mesmo grupo) para o experimento ter validade.

Ops toggles#

Controlam aspectos operacionais em produção: ligar/desligar uma funcionalidade pesada sob carga, ativar um caminho de degradação graciosa. O kill switch é o exemplo mais importante — um interruptor para desativar rapidamente algo que está causando problema. Alguns ops toggles são de vida longa, permanecendo como válvulas de controle permanentes.

Permission toggles#

Controlam quais funcionalidades cada usuário ou plano vê — recursos premium, acesso antecipado para beta testers. São de vida longa por natureza, porque fazem parte da lógica de produto, não de entrega. Aqui a "flag" na prática se confunde com autorização e deve seguir as regras de authz (decisão no servidor, nunca confiável no cliente).

A confusão perigosa é tratar um release toggle como se fosse permanente (e nunca removê-lo) ou um permission toggle como temporário. Nomeie e documente o tipo de cada flag desde o nascimento.

Rollout progressivo: ligando aos poucos#

O maior ganho operacional das flags é poder ativar uma funcionalidade gradualmente, observando o impacto antes de expor todo mundo. Em vez de um big-bang, você abre a torneira devagar:

``text Dia 1: novo_checkout = 1% dos usuários -> observa erros, latência Dia 2: novo_checkout = 10% -> métricas saudáveis, segue Dia 3: novo_checkout = 50% Dia 4: novo_checkout = 100% ``

Se, em qualquer etapa, as métricas degradarem — taxa de erro sobe, conversão cai, latência dispara — você volta a flag para o percentual anterior instantaneamente. Isso é um rollback sem deploy: o código problemático continua em produção, mas desligado. Compare com o rollback tradicional, que exige reimplantar a versão anterior e leva minutos ou mais.

O direcionamento pode ir além do percentual: ativar primeiro para usuários internos (dogfooding), depois para um beta, depois por região, por plano, por qualquer atributo. A flag vira um bisturi para controlar exatamente quem é exposto ao novo.

O kill switch: sua rede de segurança#

Toda funcionalidade nova de risco deveria nascer atrás de um kill switch — uma flag cujo único propósito é desligar aquilo rápido. Quando um alerta dispara às três da manhã por causa da feature que subiu ontem, a diferença entre "desligo a flag em dez segundos" e "preciso preparar, revisar e implantar um rollback" é a diferença entre um soluço e um incidente.

``python # Caminho protegido por kill switch com degradação graciosa. if flags.is_enabled("recomendacoes_ml"): try: return servico_ml.recomendar(usuario) except Exception as e: logger.error("recomendacao_ml_falhou", trace_id=trace_id, erro=str(e)) return recomendacoes_padrao() # degrada, não quebra return recomendacoes_padrao() ``

Repare que o kill switch e a degradação graciosa andam juntos: quando a funcionalidade está desligada (ou falha), o sistema cai num comportamento padrão seguro, em vez de quebrar. É a mesma filosofia da independência de serviços — a ausência de um componente degrada a experiência, não derruba o sistema.

A dívida técnica das flags#

Aqui está o lado sombrio. Cada flag adiciona um if no código, e cada if dobra os caminhos possíveis. Um punhado de flags convive bem; dezenas de flags esquecidas transformam o código em um labirinto onde ninguém sabe mais quais combinações são realmente testadas ou usadas. Flags acumuladas são dívida técnica que rende juros compostos.

Os problemas concretos:

  • Explosão combinatória: N flags criam até 2^N combinações de estado. Testar

todas é impossível; na prática, você testa só as que imagina, e as outras viram bugs latentes.

  • Código morto disfarçado: uma flag que já está em 100% há meses ainda tem o

ramo else com o código antigo, que ninguém remove e que confunde quem lê.

  • Flags zumbi: ninguém lembra para que servem, ninguém tem coragem de

removê-las, e elas ficam ali para sempre.

A disciplina que evita isso:

  1. Toda release toggle nasce com data de validade e um responsável. Se passou

do prazo, vira tarefa de remoção prioritária.

  1. Remover a flag faz parte de terminar a feature. A funcionalidade só está

"pronta" quando está em 100%, estável, e a flag foi removida junto com o código do caminho antigo.

  1. Inventário de flags visível. Um painel que lista todas as flags ativas, seu

tipo, idade e estado. Flags velhas demais aparecem em vermelho.

  1. Limpeza periódica. Reserve tempo de manutenção para caçar e remover flags

mortas, como quem tira o lixo.

Distinguir o tipo ajuda aqui: release toggles têm de morrer; permission e alguns ops toggles são permanentes por design. O problema é quase sempre release toggle que virou permanente por inércia.

Flags e testes: a combinação que precisa ser testada#

Um risco pouco discutido é que feature flags multiplicam os estados que o sistema pode assumir, e isso tem consequência direta para os testes. Se uma funcionalidade está atrás de uma flag, tanto o caminho com a flag ligada quanto o desligado precisam funcionar — e ambos precisam de cobertura. Testar só o estado que está em produção hoje deixa o outro caminho como um campo minado: no dia em que você liga a flag, descobre que aquele ramo nunca foi exercitado.

A prática saudável é testar os dois estados relevantes de cada flag ativa, e resistir à tentação de deixar flags acumularem justamente porque cada uma dobra o espaço de teste. Quando uma release toggle chega a 100% e é removida, o número de combinações diminui e o sistema volta a ser testável de forma exaustiva. É mais um argumento para a disciplina de remoção: flags não são só dívida de leitura de código, são dívida de testabilidade.

Onde as flags são avaliadas, e a questão da confiança#

Uma decisão de arquitetura importante: a avaliação da flag acontece no servidor ou no cliente? Para qualquer coisa que envolva segurança ou autorização (os permission toggles), a resposta é categórica: no servidor. Uma flag que esconde um botão de admin no frontend é só experiência de usuário — se a rota do servidor não reverifica a permissão, um usuário mal-intencionado chama a API direto e contorna o botão escondido. Flag de UI não é controle de acesso.

Para flags de release e experimento sem implicação de segurança, avaliar no cliente é aceitável e às vezes preferível (evita uma ida ao servidor). Mas o valor que decide precisa vir de uma fonte confiável e ser resolvido de forma consistente por usuário.

Começando com o pé direito#

Feature flags são uma dessas ferramentas que resolvem problemas reais e criam outros se usadas sem disciplina. Um caminho pragmático para adotá-las bem:

  • Comece com um mecanismo simples de flags — pode ser configuração em runtime

antes de um serviço dedicado — e proteja a próxima funcionalidade de risco atrás de uma.

  • Pratique o rollout progressivo já na primeira: 1%, 10%, 50%, 100%, observando

métricas em cada degrau.

  • Trate o kill switch como item obrigatório de qualquer feature que possa quebrar

produção.

  • Nomeie, documente e datar cada flag desde o commit que a cria.
  • Faça da remoção parte da definição de pronto.

O objetivo final não é ter muitas flags — é entregar com segurança. A flag é o meio pelo qual você separa a coragem de implantar da prudência de expor, ligando o novo devagar e podendo voltar atrás num piscar de olhos. Usada com disciplina, ela transforma o deploy de um evento tenso em um não-evento, e é isso que permite a um time entregar muitas vezes ao dia sem prender a respiração a cada push.

Leituras relacionadas

Nenhum comentário ainda

Seja o primeiro a comentar.

Deixe seu comentário

Entre com sua conta Canverly para comentar. Você pode usar a mesma conta em qualquer site da rede.

Entrar com Canverly