Introdução
Se você já passou por alguma dessas situações, este artigo é pra você:
- Precisou fazer rollback de um deploy e isso bloqueou toda a equipe de subir código
- Teve conflitos intermináveis na branch develop porque várias features estavam sendo desenvolvidas ao mesmo tempo
- Quis testar uma funcionalidade em produção apenas com um grupo específico de usuários antes de liberar pra todos
- Descobriu um bug crítico em produção e precisou esperar um novo deploy pra resolver
Feature Flags (ou Feature Toggles) resolvem todos esses problemas. Neste guia, vou mostrar passo a passo como implementei feature flags em uma aplicação Next.js usando ConfigCat como serviço externo e React Context API como camada de abstração — uma arquitetura desacoplada, escalável e pronta pra produção.
O que são Feature Flags?
Feature Flags são interruptores que permitem ligar e desligar funcionalidades da sua aplicação sem precisar fazer deploy. O código da feature já está em produção, mas só é executado quando a flag está ativa.
Pense assim: é como ter um painel de controle onde você decide, em tempo real, o que cada usuário vê na aplicação.
O que você ganha com isso?
- ✅ Deploy contínuo sem medo — suba o código com a feature desligada
- ✅ Teste em produção com segurança — ligue apenas pro seu usuário
- ✅ Kill switch instantâneo — desligou a flag, a feature some em segundos
- ✅ Rollout gradual — libere pra 10%, depois 50%, depois 100%
- ✅ Sem conflitos de branch — todo mundo sobe pra main/develop, a flag controla quem vê o quê
Por que ConfigCat?
Existem várias ferramentas de feature flags no mercado (LaunchDarkly, Unleash, Split.io). Escolhi o ConfigCat por:
- Interface intuitiva — dashboard simples e direto ao ponto
- Suporte nativo a React — SDK com Provider e hooks prontos
- Targeting avançado — controle por usuário, atributos customizados, porcentagem
- Plano gratuito generoso — suficiente pra começar
- Polling automático — atualiza os valores das flags periodicamente sem você precisar fazer nada
Arquitetura da Solução
A decisão mais importante da implementação: não acoplar a aplicação ao ConfigCat.
Se amanhã você precisar trocar de ferramenta, só altera o Provider. Nenhum componente da aplicação sabe que o ConfigCat existe.
Estrutura de pastas
src/
├── utils/consts/
│ └── featureFlags.ts # Constantes das flags + SDK keys
├── providers/feature-flags/
│ └── featureFlagsContext.tsx # Context + Provider + sincronização
└── pages/
└── _app.tsx # Provider na árvore de componentes
Fluxo da arquitetura
ConfigCat (serviço externo)
↓ polling a cada N segundos
ConfigCatReactProvider (engine — busca, cache, polling)
↓
ConfigCatSync (sincroniza user + busca flags boolean e string + escuta mudanças)
↓ armazena no useState
FeatureFlagsContext.Provider (Context próprio do projeto)
↓ expõe via useContext
Componentes (consomem com getFlag ou getStringFlag, não sabem que ConfigCat existe)
Implementação Passo a Passo
1. Instalação
npm install configcat-react
2. Constantes tipadas
Primeiro, crie as constantes das flags e as SDK keys. A implementação suporta dois tipos de flags: boolean (liga/desliga) e string (valor variável, útil para A/B testing e conteúdo dinâmico).
// src/utils/consts/featureFlags.ts
export const featureFlags = {
SHOW_DASHBOARD: 'showDashboard',
ENABLE_NEW_CHECKOUT: 'enableNewCheckout'
} as const
export const stringFeatureFlags = {
ACTIVE_PROMOTION: 'activePromotion'
} as const
export type FeatureFlagKey = (typeof featureFlags)[keyof typeof featureFlags]
export type StringFeatureFlagKey = (typeof stringFeatureFlags)[keyof typeof stringFeatureFlags]
export const configCatSdkKeys = {
TEST: '<your-configcat-sdk-key-test>',
PRODUCTION: '<your-configcat-sdk-key-production>'
} as const
Por que tipar? O TypeScript garante que você não vai digitar o nome errado de uma flag. Se tentar usar uma string que não existe no objeto, o compilador avisa.
Por que dois objetos separados? Flags boolean e string têm contratos de retorno diferentes — { isEnabled, isLoading } vs { value, isLoading }. Separar os objetos permite tipar cada método (getFlag e getStringFlag) de forma precisa, sem abrir mão de type safety.
Por que as SDK keys estão no código e não em .env? As SDK keys do ConfigCat são públicas por design — elas só permitem leitura das flags, não alteração. Colocá-las no código junto com uma função de detecção de ambiente (como veremos a seguir) elimina a necessidade de gerenciar arquivos .env por ambiente.
Agora exporte as constantes no barrel do projeto pra que fiquem acessíveis:
// src/utils/consts/index.ts
import { featureFlags, stringFeatureFlags, configCatSdkKeys } from './featureFlags'
const Consts = {
// ... outras constantes do projeto
featureFlags,
stringFeatureFlags,
configCatSdkKeys
}
export default Consts
E exporte os tipos:
// src/utils/index.ts
export type { FeatureFlagKey, StringFeatureFlagKey } from './consts/featureFlags'
3. Detecção de ambiente
Em vez de depender de variáveis de ambiente (.env.local, .env.production), use uma função que detecta o ambiente em runtime:
// src/lib/getIsProduction.ts
const hostsProduction = [
'app.meudominio.com.br',
'app-stg.meudominio.com.br'
]
const getIsProduction = () =>
process.env.BUILD_ENV === 'production' ||
(typeof window !== 'undefined' &&
hostsProduction.includes(window.location.host))
export default getIsProduction
Isso permite que o Provider escolha a SDK key correta automaticamente, sem depender de arquivos .env.
4. O Provider — coração da implementação
Aqui é onde tudo acontece. O Provider tem 3 responsabilidades:
- Inicializar o ConfigCat com a SDK key correta
- Sincronizar os dados do usuário logado com o ConfigCat (pra targeting)
- Buscar todas as flags e expor via Context próprio do projeto
// src/providers/feature-flags/featureFlagsContext.tsx
'use client'
import {
createContext,
useCallback,
useContext,
useEffect,
useMemo,
useState
} from 'react'
import {
ConfigCatProvider as ConfigCatReactProvider,
useConfigCatClient,
User
} from 'configcat-react'
import { getIsProduction } from 'lib'
import { Consts, FeatureFlagKey, StringFeatureFlagKey } from 'utils'
import { UserContext } from 'providers/user/userContext'
type FlagState = {
value: boolean | string
loading: boolean
}
type FeatureFlagsContextProps = {
flags: Record<string, FlagState>
getFlag: (key: FeatureFlagKey) => { isEnabled: boolean; isLoading: boolean }
getStringFlag: (key: StringFeatureFlagKey) => { value: string; isLoading: boolean }
}
const defaultFlagState = { isEnabled: false, isLoading: true }
const defaultStringFlagState = { value: '', isLoading: true }
export const FeatureFlagsContext = createContext<FeatureFlagsContextProps>({
flags: {},
getFlag: () => defaultFlagState,
getStringFlag: () => defaultStringFlagState
})
Detalhe importante: o defaultFlagState retorna isEnabled: false e isLoading: true. O defaultStringFlagState retorna value: '' e isLoading: true. Enquanto as flags não carregaram, nenhuma feature controlada por flag aparece — comportamento seguro por padrão.
ConfigCatSync — o componente que faz a mágica
const ConfigCatSync = ({ children }: { children: React.ReactNode }) => {
const { user } = useContext(UserContext)
const client = useConfigCatClient()
const [flags, setFlags] = useState<Record<string, FlagState>>({})
// Sincroniza dados do usuário logado com o ConfigCat
useEffect(() => {
if (!client) return
if (user) {
const configCatUser = new User(user.email, user.email, undefined, {
role: user.role || '',
plan: user.plan || '',
is_admin: user.isAdmin ? '1' : '0'
// Adicione quantos atributos precisar pro targeting
})
client.setDefaultUser(configCatUser)
} else {
client.clearDefaultUser()
}
}, [client, user])
// Busca todas as flags e escuta mudanças
useEffect(() => {
if (!client) return
const fetchAllFlags = async () => {
const booleanKeys = Object.values(Consts.featureFlags)
const stringKeys = Object.values(Consts.stringFeatureFlags)
const booleanEntries = await Promise.all(
booleanKeys.map(async (key) => {
const value = await client.getValueAsync(key, false)
return [key, { value: Boolean(value), loading: false }] as const
})
)
const stringEntries = await Promise.all(
stringKeys.map(async (key) => {
const value = await client.getValueAsync(key, '')
return [key, { value: String(value), loading: false }] as const
})
)
setFlags(Object.fromEntries([...booleanEntries, ...stringEntries]))
}
fetchAllFlags()
const handler = () => {
fetchAllFlags()
}
client.on('configChanged', handler)
return () => {
client.off('configChanged', handler)
}
}, [client, user])
const getFlag = useCallback(
(key: FeatureFlagKey) => {
const flag = flags[key]
if (!flag) return defaultFlagState
return { isEnabled: Boolean(flag.value), isLoading: flag.loading }
},
[flags]
)
const getStringFlag = useCallback(
(key: StringFeatureFlagKey) => {
const flag = flags[key]
if (!flag) return defaultStringFlagState
return { value: String(flag.value), isLoading: flag.loading }
},
[flags]
)
const contextValue = useMemo(
() => ({ flags, getFlag, getStringFlag }),
[flags, getFlag, getStringFlag]
)
return (
<FeatureFlagsContext.Provider value={contextValue}>
{children}
</FeatureFlagsContext.Provider>
)
}
O que está acontecendo aqui:
- O primeiro
useEffectsincroniza os dados do usuário logado com o ConfigCat. Isso permite targeting por atributos (ex: "mostrar só pra admins") - O segundo
useEffectbusca todas as flags de uma vez — boolean e string separadamente — e armazena nouseState. Note queuserfaz parte das dependências: quando o usuário troca (ex: login/logout), as flags são rebuscadas automaticamente com o novo contexto de targeting - O
client.on('configChanged', handler)escuta mudanças: quando o ConfigCat detecta uma atualização via polling, o handler rebusca todas as flags automaticamente, sem refresh da página - O
useMemonocontextValueevita re-renders desnecessários nos componentes consumidores
O Provider principal
type FeatureFlagsProviderProps = {
children: React.ReactNode
}
const FeatureFlagsProvider = ({ children }: FeatureFlagsProviderProps) => {
const sdkKey = getIsProduction()
? Consts.configCatSdkKeys.PRODUCTION
: Consts.configCatSdkKeys.TEST
return (
<ConfigCatReactProvider
sdkKey={sdkKey}
options={{ pollIntervalSeconds: 3600 }}
>
<ConfigCatSync>{children}</ConfigCatSync>
</ConfigCatReactProvider>
)
}
export default FeatureFlagsProvider
Sobre o pollIntervalSeconds: o padrão do ConfigCat é 60 segundos. Usamos 3600 (1 hora) porque, na maioria dos casos, flags não precisam propagar imediatamente — e intervalos curtos consomem quota do plano desnecessariamente. Se o seu cenário exigir propagação mais rápida (ex: kill switch urgente), reduzir para 60 ou 120 é razoável. O importante é calibrar conforme a necessidade real, não usar o menor valor possível.
5. Adicionar na árvore de componentes
// src/pages/_app.tsx
import FeatureFlagsProvider from 'providers/feature-flags/featureFlagsContext'
function App({ Component, pageProps }) {
return (
<UserProvider>
<FeatureFlagsProvider>
<Component {...pageProps} />
</FeatureFlagsProvider>
</UserProvider>
)
}
Ordem importa: o FeatureFlagsProvider precisa estar dentro do UserProvider, porque o ConfigCatSync consome o UserContext pra sincronizar os dados do usuário.
Configurando no Dashboard do ConfigCat
Criando uma flag boolean
- Acesse o dashboard do ConfigCat
- Crie uma feature flag do tipo On/Off Toggle com o nome exato que você definiu na constante (ex:
showDashboard) - Configure o valor padrão como
OFF
Criando uma flag string
- No dashboard, crie uma feature flag do tipo Text
- Use o nome exato da constante em
stringFeatureFlags(ex:activePromotion) - Configure o valor padrão como string vazia ou um valor seguro
Configurando ambientes
O ConfigCat separa ambientes por SDK key. Cada ambiente tem sua própria key:
- Test/Development — use a key de teste
- Production — use a key de produção
Isso significa que você pode ter a flag ON em teste e OFF em produção ao mesmo tempo.
Consumindo nos Componentes
Exemplo 1: Controlar visibilidade de um item no menu
import { useContext, useMemo } from 'react'
import { Consts } from 'utils'
import { FeatureFlagsContext } from 'providers/feature-flags/featureFlagsContext'
const Menu = ({ loggedUser }) => {
const { getFlag } = useContext(FeatureFlagsContext)
const { isEnabled: showDashboard } = getFlag(
Consts.featureFlags.SHOW_DASHBOARD
)
const menuItems = useMemo(() => {
const base = [
{ label: 'Parcelas', url: '/app/parcelas' },
{ label: 'Recibos', url: '/app/recibos' }
]
if (loggedUser.isAdmin && showDashboard) {
base.unshift({ label: 'Dashboard', url: '/app/dashboard' })
}
return base
}, [loggedUser, showDashboard])
return (
<nav>
<ul>
{menuItems.map((item) => (
<li key={item.url}>
<a href={item.url}>{item.label}</a>
</li>
))}
</ul>
</nav>
)
}
Perceba: o componente importa FeatureFlagsContext — não sabe nada sobre ConfigCat. Se amanhã trocar de ferramenta, este componente não muda.
Exemplo 2: Proteger uma página inteira com redirect
import { useContext, useEffect } from 'react'
import { useRouter } from 'next/router'
import { Consts } from 'utils'
import { FeatureFlagsContext } from 'providers/feature-flags/featureFlagsContext'
const DashboardPage = () => {
const { push } = useRouter()
const { getFlag } = useContext(FeatureFlagsContext)
const { isEnabled: showDashboard, isLoading } = getFlag(
Consts.featureFlags.SHOW_DASHBOARD
)
useEffect(() => {
if (!isLoading && !showDashboard) {
push('/app')
}
}, [isLoading, showDashboard, push])
if (isLoading) return null
return <div>Conteúdo do Dashboard</div>
}
Por que checar isLoading? Sem essa checagem, o componente faria redirect imediatamente no primeiro render (porque isEnabled começa como false enquanto as flags carregam). O isLoading garante que o redirect só acontece depois que o ConfigCat respondeu.
Exemplo 3: Exibição condicional de um componente
import { useContext } from 'react'
import { Consts } from 'utils'
import { FeatureFlagsContext } from 'providers/feature-flags/featureFlagsContext'
const HomePage = () => {
const { getFlag } = useContext(FeatureFlagsContext)
const { isEnabled: enableNewCheckout } = getFlag(
Consts.featureFlags.ENABLE_NEW_CHECKOUT
)
return (
<div>
<h1>Bem-vindo</h1>
{enableNewCheckout ? <NewCheckout /> : <LegacyCheckout />}
</div>
)
}
Exemplo 4: Flag string para conteúdo dinâmico
Flags string são ideais quando você precisa não só de ligar/desligar, mas de controlar qual variante exibir — A/B testing, banners sazonais, temas, e afins.
import { useContext } from 'react'
import { Consts } from 'utils'
import { FeatureFlagsContext } from 'providers/feature-flags/featureFlagsContext'
const PromoBanner = () => {
const { getStringFlag } = useContext(FeatureFlagsContext)
const { value: activePromotion, isLoading } = getStringFlag(
Consts.stringFeatureFlags.ACTIVE_PROMOTION
)
if (isLoading || !activePromotion) return null
return <Banner type={activePromotion} />
}
No dashboard do ConfigCat, você configura o valor da flag como 'black-friday', 'cyber-monday' ou string vazia (desligado). Zero deploy pra trocar a campanha ativa.
User Targeting — A Mágica de Verdade
A parte mais poderosa das feature flags é o targeting. Com os dados do usuário sincronizados no ConfigCatSync, você pode criar regras no dashboard como:
Targeting por email (testar com seu próprio usuário)
IF User.email IS ONE OF ["dev@empresa.com"]
THEN serve: ON
To everyone else: OFF
Targeting por atributo (liberar pra admins)
IF User.is_admin EQUALS "1"
THEN serve: ON
To everyone else: OFF
Rollout por porcentagem
10% dos usuários: ON
90% dos usuários: OFF
Isso permite um rollout gradual: comece com 10%, monitore, aumente pra 50%, e finalmente 100%.
Testes
Mock do ConfigCat para Jest
Como o ConfigCat é uma dependência externa, precisamos mocká-lo nos testes. O mock deve cobrir todos os símbolos usados pelo featureFlagsContext.tsx:
// __mocks__/configcat-react.js
module.exports = {
ConfigCatProvider: ({ children }) => children,
useConfigCatClient: () => ({
getValueAsync: (key, defaultValue) => Promise.resolve(defaultValue),
setDefaultUser: () => {},
clearDefaultUser: () => {},
on: () => {},
off: () => {}
}),
User: class User {
constructor() {}
}
}
Configurar no jest.config.js
module.exports = {
moduleNameMapper: {
'^configcat-react$': '<rootDir>/__mocks__/configcat-react.js'
}
}
Mock do Context nos testes de componentes
Na prática, a maioria dos testes de componentes não precisa exercitar o Provider inteiro — basta mockar o Context diretamente. Inclua getStringFlag junto com getFlag:
jest.mock('providers/feature-flags/featureFlagsContext', () => ({
FeatureFlagsContext: {
_currentValue: {
flags: {},
getFlag: () => ({ isEnabled: true, isLoading: false }),
getStringFlag: () => ({ value: 'default', isLoading: false })
}
}
}))
Isso faz com que todas as flags boolean retornem true e as string retornem 'default' nos testes — comportamento padrão que geralmente você quer ao testar o caminho feliz.
Para testar o cenário com flag desligada:
jest.mock('providers/feature-flags/featureFlagsContext', () => ({
FeatureFlagsContext: {
_currentValue: {
flags: {},
getFlag: () => ({ isEnabled: false, isLoading: false }),
getStringFlag: () => ({ value: '', isLoading: false })
}
}
}))
Para testar o estado de carregamento:
jest.mock('providers/feature-flags/featureFlagsContext', () => ({
FeatureFlagsContext: {
_currentValue: {
flags: {},
getFlag: () => ({ isEnabled: false, isLoading: true }),
getStringFlag: () => ({ value: '', isLoading: true })
}
}
}))
Casos de Uso Reais
1. Deploy Seguro
Você desenvolveu uma feature nova. Em vez de esperar pra fazer merge só quando estiver 100% pronta:
- Suba o código com a flag
OFF - No dashboard, ligue apenas pro seu email
- Teste em produção com dados reais
- Quando estiver pronto, ligue pra todos
Zero conflito de branch. Zero rollback.
2. Kill Switch
Feature causando problemas em produção?
- Abra o dashboard do ConfigCat
- Desligue a flag
- Em até uma hora (ou o intervalo de polling configurado), a feature desaparece
Sem deploy. Sem rollback. Sem estresse.
3. Apresentação para Stakeholders
Quer mostrar uma feature nova só pros diretores antes de liberar?
- Crie uma regra de targeting com os emails dos diretores
- Ligue a flag
- Eles veem a feature, o resto dos usuários não
4. Rollout Gradual
Feature nova que pode impactar performance?
- Dia 1: 10% dos usuários
- Dia 3: 50% dos usuários
- Dia 5: 100% dos usuários
Se em qualquer momento algo der errado, volte pra 0%.
5. Campanha ou Conteúdo Dinâmico (flag string)
Você tem um banner que muda conforme a campanha ativa. Em vez de fazer deploy a cada troca:
- Crie uma flag string
activePromotionno ConfigCat - Configure o valor como
'black-friday'quando a campanha começa - Mude para
''(vazio) quando terminar
O componente reage automaticamente quando o polling detecta a mudança — sem deploy, sem redeploy, sem acionar o time de infra.
Boas Práticas
1. Nomenclatura consistente
Use camelCase nas flags (padrão do ConfigCat) e UPPER_SNAKE_CASE nas constantes:
// ✅ Bom — claro e descritivo
featureFlags = {
SHOW_DASHBOARD: 'showDashboard',
ENABLE_NEW_CHECKOUT: 'enableNewCheckout'
}
stringFeatureFlags = {
ACTIVE_PROMOTION: 'activePromotion'
}
// ❌ Ruim — ambíguo
featureFlags = {
DASH: 'dash',
CHECKOUT: 'checkout'
}
2. Escolha o tipo certo de flag
| Use boolean quando... | Use string quando... |
|---|---|
| Ligar/desligar uma feature | Controlar qual variante exibir |
| Proteger uma rota | Selecionar um tema ou layout |
| Feature em rollout gradual | A/B testing com múltiplas variantes |
| Kill switch de emergência | Conteúdo dinâmico (banners, campanhas) |
3. Limpeza de flags antigas
Flags são código temporário. Quando a feature estiver 100% liberada e estável:
- Remova a flag do código (o
ifcomgetFlagou o componente comgetStringFlag) - Remova a constante do
featureFlagsoustringFeatureFlags - Delete a flag do dashboard do ConfigCat
Flag esquecida é dívida técnica.
4. Comportamento seguro por padrão
O defaultFlagState retorna isEnabled: false e o defaultStringFlagState retorna value: ''. Se o ConfigCat estiver fora do ar ou demorar pra responder, nenhuma feature nova aparece — o usuário vê a versão estável da aplicação.
5. Use isLoading em páginas protegidas
Sempre cheque isLoading antes de tomar decisões como redirect:
// ✅ Bom — espera carregar antes de decidir
const { isEnabled, isLoading } = getFlag(Consts.featureFlags.SHOW_DASHBOARD)
useEffect(() => {
if (!isLoading && !isEnabled) {
push('/app')
}
}, [isLoading, isEnabled, push])
// ❌ Ruim — redireciona antes de saber o valor real
const { isEnabled } = getFlag(Consts.featureFlags.SHOW_DASHBOARD)
useEffect(() => {
if (!isEnabled) {
push('/app') // Vai redirecionar no primeiro render!
}
}, [isEnabled, push])
Vantagens da Arquitetura
Desacoplamento total
// Componentes não conhecem ConfigCat
import { FeatureFlagsContext } from 'providers/feature-flags/featureFlagsContext'
const { getFlag, getStringFlag } = useContext(FeatureFlagsContext)
Fácil migração
Para trocar ConfigCat por outra ferramenta (ex: LaunchDarkly), você altera apenas o ConfigCatSync e o FeatureFlagsProvider. Os componentes continuam usando useContext(FeatureFlagsContext) + getFlag/getStringFlag — não mudam nada.
Estado centralizado
Todas as flags são buscadas uma vez e compartilhadas via Context. Se 10 componentes usam a mesma flag, o ConfigCat é consultado uma vez só — não 10 vezes.
Reatividade automática
O listener configChanged garante que quando uma flag muda no dashboard, todos os componentes que a consomem atualizam automaticamente, sem refresh da página. Isso vale tanto para flags boolean quanto string.
Dois tipos de flag, um contrato unificado
O Context expõe getFlag e getStringFlag com contratos claros e tipados. Componentes nunca lidam com any ou precisam fazer cast — o TypeScript guia o uso correto desde o autocompletar.
Conclusão
Feature Flags transformaram a forma como fazemos deploy. Com ConfigCat como engine e React Context API como camada de abstração, conseguimos:
- ✅ Deploy contínuo sem medo
- ✅ Testes em produção com segurança
- ✅ Kill switch instantâneo
- ✅ Targeting avançado por usuário
- ✅ Suporte a flags boolean e string
- ✅ Estado centralizado e reativo
- ✅ Arquitetura desacoplada — pronta pra trocar de ferramenta
- ✅ TypeScript garantindo type safety nas flags
O investimento de criar a camada de abstração com Context API vale muito a pena. O código fica limpo, testável e preparado pro futuro.
Indo Além — O que este guia não cobre
O que implementamos aqui é uma base sólida e pronta pra produção. Mas feature flags como conceito têm muito mais profundidade. Se você quiser continuar explorando:
Outros tipos de valor
Além de boolean e string, ferramentas como ConfigCat suportam flags do tipo int, double e até JSON. Isso abre espaço para casos como configurar limites dinâmicos (rate limit, tamanho de paginação, timeout de requisição) ou passar objetos de configuração inteiros sem deploy.
Flags no servidor
A implementação deste artigo é inteiramente client-side. Em aplicações Next.js com uso intenso de SSR ou Server Components, você pode — e muitas vezes deve — avaliar flags no servidor, antes de renderizar a página. Isso evita flashes de conteúdo (o usuário nunca vê o estado "carregando") e permite decisões de roteamento ainda na borda.
Testes com flags em múltiplos estados no CI
Uma flag desligada em produção não significa que o código por trás dela está livre de bugs. Estratégias de CI/CD mais avançadas rodam o pipeline com a flag ligada e desligada, garantindo que ambos os caminhos sejam validados antes do merge.
Gestão do ciclo de vida das flags
Flags acumuladas viram dívida técnica silenciosa. Existem abordagens para rastrear a idade de cada flag, definir uma data de expiração desde a criação, e automatizar alertas quando uma flag passa do prazo esperado — antes que ela vire um if esquecido no código.
Plataformas de experimentação
Feature flags são o passo zero de um experimento. Ferramentas como LaunchDarkly, Split.io e GrowthBook vão além: medem o impacto estatístico de cada variante, calculam significância e ajudam a tomar decisões de produto baseadas em dados — não em intuição.
Cada um desses tópicos rende um artigo próprio. O importante é que a arquitetura que construímos aqui já está preparada para evoluir em qualquer dessas direções — o desacoplamento via Context API garante isso.
Recursos
Escrito por Guilherme Marucchi — Meu LinkedIn





Top comments (0)