Pular para o conteúdo

Arquitetura de software · Confiabilidade e segurança · 6 min de leitura

Feature flags: separar deploy de lançamento

Um interruptor no código permite publicar uma funcionalidade desligada, ligar para 1% das pessoas, comparar resultados e desligar em segundos se der problema.

Deploy → Serviço de flagsServiço de flags → App / API: regrasregrasApp / API → 1% → 10% → 100%Kill switch → Serviço de flagsDeploy — flag desligadaDeployflag desligadaServiço de flags — regras e %Serviço de flagsregras e %App / API — avalia a flagApp / APIavalia a flag1% → 10% → 100% — novo checkout1% → 10% → 100%novo checkoutKill switch — desliga em segundosKill switchdesliga em segundos

Arraste para o lado para ver o diagrama inteiro.

Subir a porcentagem é mudar uma configuração, não fazer um novo deploy; voltar atrás também.

Os quatro tipos

  • De lançamento: código incompleto vai para produção desligado (permite trunk-based development). Vida curta.
  • De experimento: teste A/B — metade vê a versão nova e medimos o resultado.
  • Operacionais: kill switch para desligar algo pesado durante um pico. Podem durar anos.
  • De permissão: funcionalidade só para plano pago, beta ou equipe interna.

Lançamento gradual bem feito

  • A fatia é determinística: um hash de flag + id_do_usuario decide, então a mesma pessoa sempre vê a mesma versão.
  • Comece pela equipe interna, depois 1%, 10%, 50%, 100% — olhando erros e métricas de negócio a cada passo.
  • Avalie a flag no servidor sempre que possível; no app, guarde a última configuração para funcionar offline e com um valor padrão seguro.
  • Padrões abertos como o OpenFeature evitam prender o código a um fornecedor.

A dívida das flags

Cada flag dobra os caminhos possíveis do código. Flags esquecidas viram armadilhas — a Knight Capital perdeu US$ 440 milhões em 2012 em parte por reaproveitar uma flag antiga que reativou código morto. Regras práticas: dono e data de validade para cada flag de lançamento, remover o código antigo assim que chegar a 100%, testes para os dois estados das flags ativas e um painel listando as flags velhas.

No código

✓ ExemploKotlin
/** Mesmo usuário, mesma resposta: o hash de flag + id cai sempre no mesmo balde de 0 a 99. */
fun bucket(flag: String, userId: String): Int {
    val digest = MessageDigest.getInstance("SHA-256").digest("$flag:$userId".toByteArray())
    val n = ((digest[0].toInt() and 0xff) shl 8) or (digest[1].toInt() and 0xff)
    return n % 100
}

data class FlagRule(val enabled: Boolean, val percent: Int, val allowList: Set<String> = emptySet())

class Flags(private val rules: () -> Map<String, FlagRule>) {
    fun isOn(flag: String, userId: String): Boolean {
        val rule = rules()[flag] ?: return false // desconhecida = desligada (padrão seguro)
        if (!rule.enabled) return false           // kill switch
        if (userId in rule.allowList) return true // equipe interna primeiro
        return bucket(flag, userId) < rule.percent
    }
}

// Remover este if (e o checkout antigo) quando a flag chegar a 100%.
if (flags.isOn("novo-checkout", user.id)) NewCheckout() else OldCheckout()

A fatia não depende de sorteio a cada abertura: subir de 10% para 20% mantém os primeiros 10% e acrescenta outros. Flag desconhecida fica desligada.

Em resumo

Vantagens e custos

Vantagens
  • Lançamentos graduais e reversíveis em segundos.
  • Testes A/B com o mesmo código.
  • Integração contínua sem ramos longos.
Custos e riscos
  • Caminhos de código multiplicados.
  • Flags esquecidas viram dívida e risco.
  • Mais uma dependência em tempo de execução.

Perguntar à IA

Monte um prompt pronto sobre Feature flags: separar deploy de lançamento na sua linguagem e no seu caso, e abra num chat gratuito.

ChatGPT Claude Perplexity

O prompt vai para o site que você escolher. Não cole senhas, tokens nem dados reais de clientes. Para Gemini e outros, copie e cole.

Referências

Continue aprendendo

Todos os temas de arquitetura de software →