Disponível para freelancerEntre em contato para que eu possa ajudar seu negócio a crescer ou tirar sua ideia do papel!

Estou interessado
Feature Flags no Frontend: Suba o Código, Lance Quando Estiver Pronto

Feature Flags no Frontend: Suba o Código, Lance Quando Estiver Pronto

Você fez o merge. A funcionalidade está em produção. Mas o negócio ainda não está pronto para lançar.

Sem feature flags, as opções são: segurar o merge ou aceitar o risco. Com feature flags, você sobe o código e ativa quando estiver pronto.


O Que É uma Feature Flag?

Uma feature flag (também chamada de feature toggle) é uma condicional que controla se uma funcionalidade está visível ou ativa.

if (flags.novoCheckout) {
  return <NovoFluxoCheckout />
}

return <CheckoutAntigo />

A funcionalidade existe em produção. Ninguém vê até você ativar a flag.


Por Que Isso Importa

Sem flagsCom flags
Aguardar para fazer mergeMerge a qualquer momento
Deploys arriscadosRollouts graduais
Todos os usuários recebem a mudançaVocê controla quem vê o quê
Rollback = novo deployRollback = virar o switch

Times que entregam com frequência usam feature flags para separar deploy de lançamento.


A Implementação Mais Simples

Comece com variáveis de ambiente. Sem bibliotecas, sem complexidade.

// lib/flags.ts
export const flags = {
  novoCheckout: process.env.NEXT_PUBLIC_FLAG_NOVO_CHECKOUT === 'true',
  betaDashboard: process.env.NEXT_PUBLIC_FLAG_BETA_DASHBOARD === 'true',
}
// components/Checkout.tsx
import { flags } from '@/lib/flags'

export default function Checkout() {
  if (flags.novoCheckout) {
    return <NovoFluxoCheckout />
  }

  return <CheckoutAntigo />
}

Defina a variável no seu pipeline de CI/CD ou no .env.local:

NEXT_PUBLIC_FLAG_NOVO_CHECKOUT=true

Funciona bem para toggles por ambiente (staging vs produção). A desvantagem: mudar uma flag exige um novo deploy.


Flags em Runtime com React Context

Para flags que mudam sem redeploy, busque-as em runtime e exponha via context.

// lib/flags-context.tsx
'use client'

import { createContext, useContext } from 'react'

type Flags = {
  novoCheckout: boolean
  betaDashboard: boolean
}

const FlagsContext = createContext<Flags>({ novoCheckout: false, betaDashboard: false })

export function FlagsProvider({ flags, children }: { flags: Flags; children: React.ReactNode }) {
  return <FlagsContext.Provider value={flags}>{children}</FlagsContext.Provider>
}

export function useFlags() {
  return useContext(FlagsContext)
}

Busque as flags no servidor e injete no layout raiz:

// app/[locale]/layout.tsx
import { FlagsProvider } from '@/lib/flags-context'

async function getFlags() {
  const res = await fetch('https://sua-api-de-flags.com/flags', { next: { revalidate: 60 } })
  return res.json()
}

export default async function RootLayout({ children }) {
  const flags = await getFlags()

  return (
    <html>
      <body>
        <FlagsProvider flags={flags}>{children}</FlagsProvider>
      </body>
    </html>
  )
}

Qualquer componente pode ler as flags sem prop drilling:

'use client'

import { useFlags } from '@/lib/flags-context'

export default function Header() {
  const { betaDashboard } = useFlags()

  return <nav>{betaDashboard && <a href="/beta">Beta Dashboard</a>}</nav>
}

Ferramentas de Terceiros

Quando você precisa de segmentação por usuário, testes A/B ou uma interface para gerenciar flags sem tocar no código, use um serviço dedicado.

FerramentaPontos Fortes
LaunchDarklyEnterprise, segmentação avançada
GrowthBookOpen-source, A/B testing integrado
UnleashSelf-hostável, bom para times
Vercel FlagsIntegração nativa com Next.js
FlagsmithSimples, boa camada gratuita

Exemplo com Vercel Flags

import { flag } from '@vercel/flag/next'

export const novoCheckoutFlag = flag<boolean>({
  key: 'novo-checkout',
  defaultValue: false,
  decide() {
    return false
  },
})
// app/checkout/page.tsx
import { novoCheckoutFlag } from '@/flags'

export default async function CheckoutPage() {
  const mostrarNovoCheckout = await novoCheckoutFlag()

  return mostrarNovoCheckout ? <NovoFluxoCheckout /> : <CheckoutAntigo />
}

Erros Comuns

1. Deixar flags no código para sempre

// ❌ Flags se acumulam e ninguém remove
if (flags.funcionalidadeAntigaDoQ1) { ... }
if (flags.experimentoDoAnoPassado) { ... }
// ✅ Defina uma data de limpeza ao criar a flag
// TODO: remover esta flag após 2026-07-01
if (flags.novoCheckout) { ... }

2. Aninhar flags dentro de flags

// ❌ Ilegível e difícil de depurar
if (flags.funcionalidadeA) {
  if (flags.funcionalidadeB) {
    if (flags.funcionalidadeC) { ... }
  }
}

Refatore: uma flag por funcionalidade, composta no nível do componente.

3. Expor flags somente de servidor para o cliente

// ❌ Exportado para o cliente — vaza configurações internas
export const flags = {
  adminPanel: process.env.ADMIN_FEATURE_FLAG === 'true',
}

Use NEXT_PUBLIC_ apenas para flags seguras de expor. Mantenha toggles sensíveis no servidor.

4. Sem valor padrão

// ❌ Quebra se flags for undefined
if (flags.novoCheckout) { ... }
// ✅ Padrão seguro
const { novoCheckout = false } = useFlags()

Quando Usar Feature Flags

Use quando:

  • A funcionalidade é grande e abrange vários PRs
  • O negócio precisa controlar o timing do lançamento
  • Você quer um rollout gradual (10% → 50% → 100%)
  • Está rodando um experimento A/B
  • A funcionalidade é arriscada e você precisa de um kill switch

Evite quando:

  • A funcionalidade é pequena e isolada
  • Você está adicionando flags para tudo (aumenta a manutenção)
  • A flag nunca é removida (vira código morto)

O Que Fazer Agora

  • Adicione um simples lib/flags.ts ao seu projeto atual
  • Identifique uma funcionalidade em andamento que se beneficiaria de uma flag
  • Defina uma política de limpeza de flags (tempo máximo de vida, responsável, PR de remoção)
  • Se o seu time entrega com frequência, avalie GrowthBook ou Vercel Flags

Feature flags separam quando você faz deploy de quando os usuários veem.

Isso não é apenas um truque de deployment — é uma disciplina que torna times mais rápidos e lançamentos mais seguros.