React & Frontend

Como Usar Feature Flags em React: LaunchDarkly, Unleash e Rollouts Graduais em Produção

13 min de leitura

Como Usar Feature Flags em React: LaunchDarkly, Unleash e Rollouts Graduais em Produção

O que são Feature Flags e por que eles importam Feature flags (ou feature toggles) são mecanismos que permitem ativar ou desativar funcionalidades em uma aplicação sem necessidade de deploy. Em vez de lançar uma feature completamente pronta para todos os usuários de uma vez, você pode controlar quem a vê, quando a vê e em que contexto. Isso revoluciona a forma como entregamos software, permitindo testes mais seguros, rollouts graduais e até experimentos A/B sem risco. Na prática, você coloca sua nova funcionalidade atrás de um condicional que verifica um flag externo. Se o flag está ativado, o usuário vê a feature; se não, ele vê o comportamento antigo. A grande diferença é que essa decisão não fica hardcoded na sua aplicação — ela vem de um serviço centralizado, como LaunchDarkly ou Unleash, permitindo mudanças em tempo real sem redeploy. Isso significa que um problema crítico pode ser desativado em segundos, experimentos podem ser pausados instantaneamente, e releases podem

<h2>O que são Feature Flags e por que eles importam</h2>

<p>Feature flags (ou feature toggles) são mecanismos que permitem ativar ou desativar funcionalidades em uma aplicação sem necessidade de deploy. Em vez de lançar uma feature completamente pronta para todos os usuários de uma vez, você pode controlar quem a vê, quando a vê e em que contexto. Isso revoluciona a forma como entregamos software, permitindo testes mais seguros, rollouts graduais e até experimentos A/B sem risco.</p>

<p>Na prática, você coloca sua nova funcionalidade atrás de um condicional que verifica um flag externo. Se o flag está ativado, o usuário vê a feature; se não, ele vê o comportamento antigo. A grande diferença é que essa decisão <strong>não fica hardcoded</strong> na sua aplicação — ela vem de um serviço centralizado, como LaunchDarkly ou Unleash, permitindo mudanças em tempo real sem redeploy. Isso significa que um problema crítico pode ser desativado em segundos, experimentos podem ser pausados instantaneamente, e releases podem ser feitos sem risco.</p>

<h2>LaunchDarkly: Gerenciamento Profissional de Flags</h2>

<p>LaunchDarkly é uma plataforma enterprise dedicada ao gerenciamento de feature flags. Ela oferece um painel intuitivo, webhooks, integrações com várias plataformas e um SDK robusto para React. Vamos implementar um exemplo prático.</p>

<h3>Instalação e Configuração Básica</h3>

<p>Primeiro, instale o SDK do LaunchDarkly para React:</p>

<pre><code class="language-bash">npm install launchdarkly-react-client-sdk</code></pre>

<p>Crie um arquivo de configuração para sua aplicação. Você precisará de uma <code>clientSideId</code> (obtida no painel do LaunchDarkly):</p>

<pre><code class="language-jsx">import { LDProvider } from &#039;launchdarkly-react-client-sdk&#039;;

const ldClient = {

clientSideId: &#039;seu-client-side-id-aqui&#039;,

context: {

kind: &#039;user&#039;,

key: &#039;user-id-unico&#039;,

email: &#039;usuario@example.com&#039;,

custom: {

plano: &#039;premium&#039;

}

}

};

function App() {

return (

&lt;LDProvider clientSideId={ldClient.clientSideId} context={ldClient.context}&gt;

&lt;YourAppContent /&gt;

&lt;/LDProvider&gt;

);

}

export default App;</code></pre>

<p>A configuração acima cria um contexto de usuário. O LaunchDarkly usa esse contexto para decidir quais flags cada usuário deve ver, permitindo segmentação por tipo de usuário, plano de assinatura, região, etc.</p>

<h3>Usando Flags no Componente</h3>

<p>Agora, use o hook <code>useFlags()</code> para acessar os flags dentro dos seus componentes:</p>

<pre><code class="language-jsx">import { useFlags } from &#039;launchdarkly-react-client-sdk&#039;;

function Dashboard() {

const flags = useFlags();

return (

&lt;div&gt;

&lt;h1&gt;Dashboard&lt;/h1&gt;

{flags.novaInterfaceUsuario ? (

&lt;NovaInterfaceDashboard /&gt;

) : (

&lt;InterfaceAntiga /&gt;

)}

&lt;/div&gt;

);

}

export default Dashboard;</code></pre>

<p>Se o flag <code>novaInterfaceUsuario</code> estiver ativado para este usuário, ele verá <code>NovaInterfaceDashboard</code>. Caso contrário, verá a versão antiga. A decisão é tomada no servidor do LaunchDarkly e sincronizada com o cliente em tempo real.</p>

<h3>Variações e Valores Personalizados</h3>

<p>Flags não precisam ser apenas booleanos. O LaunchDarkly suporta variações complexas — strings, números, objetos JSON. Você pode usar isso para A/B testing com múltiplas variações:</p>

<pre><code class="language-jsx">import { useLDClient } from &#039;launchdarkly-react-client-sdk&#039;;

function ButtonComponent() {

const ldClient = useLDClient();

const buttonText = ldClient.variation(&#039;textoBotaoCheckout&#039;, &#039;Comprar agora&#039;);

// Se o flag estiver ativado, pode retornar:

// - &quot;Comprar agora&quot; (controle)

// - &quot;Finalizar pedido&quot; (variação A)

// - &quot;Continuar&quot; (variação B)

return &lt;button&gt;{buttonText}&lt;/button&gt;;

}

export default ButtonComponent;</code></pre>

<p>O LaunchDarkly permite definir regras baseadas em contexto — por exemplo, mostrar a variação &quot;Finalizar pedido&quot; para 50% dos usuários premium e &quot;Comprar agora&quot; para o resto. Tudo gerenciado pelo painel, sem tocar no código.</p>

<h2>Unleash: Open Source e Flexibilidade</h2>

<p>Unleash é uma alternativa open source ao LaunchDarkly. Se você quer controle total sobre a infraestrutura, sem depender de serviços terceirizados, Unleash é uma ótima escolha. Ele pode ser auto-hospedado e oferece uma API simples e poderosa.</p>

<h3>Instalando o SDK do Unleash para React</h3>

<pre><code class="language-bash">npm install @unleash/proxy-client-react</code></pre>

<p>Configure o provedor Unleash em seu <code>App.jsx</code>:</p>

<pre><code class="language-jsx">import { UnleashProvider } from &#039;@unleash/proxy-client-react&#039;;

function App() {

return (

&lt;UnleashProvider

config={{

url: &#039;http://seu-servidor-unleash.com/client&#039;,

clientKey: &#039;sua-chave-cliente&#039;,

appName: &#039;minha-aplicacao&#039;,

environment: &#039;production&#039;

}}

&gt;

&lt;YourAppContent /&gt;

&lt;/UnleashProvider&gt;

);

}

export default App;</code></pre>

<h3>Acessando Flags com Unleash</h3>

<p>Use o hook <code>useFeature()</code> para verificar se uma flag está ativada:</p>

<pre><code class="language-jsx">import { useFeature } from &#039;@unleash/proxy-client-react&#039;;

function FeaturePage() {

const { isEnabled } = useFeature(&#039;nova-sessao-pagamento&#039;);

if (!isEnabled) {

return &lt;div&gt;Esta funcionalidade ainda não está disponível.&lt;/div&gt;;

}

return &lt;NovaSessionPagamento /&gt;;

}

export default FeaturePage;</code></pre>

<p>O Unleash também suporta contexto do usuário para segmentação:</p>

<pre><code class="language-jsx">import { useUnleash } from &#039;@unleash/proxy-client-react&#039;;

function ProfilePage() {

const { isEnabled } = useUnleash();

// Passar contexto personalizado

const podeAcessarBeta = isEnabled(&#039;betaAnalytics&#039;, {

userId: &#039;user-123&#039;,

tipoPlano: &#039;premium&#039;,

pais: &#039;BR&#039;

});

return podeAcessarBeta ? &lt;BetaAnalytics /&gt; : &lt;AnalyticsClassica /&gt;;

}

export default ProfilePage;</code></pre>

<h3>Estratégias Avançadas no Unleash</h3>

<p>O Unleash permite definir estratégias complexas, como ativação gradual por porcentagem de usuários. Você configura isso no painel, e o SDK automaticamente respeita:</p>

<pre><code class="language-jsx">import { useFeatures } from &#039;@unleash/proxy-client-react&#039;;

function ReleasePage() {

const { features } = useFeatures();

// Unleash internamente verifica se o hash do userId

// se enquadra nos 10% de rollout definidos no painel

const novaFeature = features.find(f =&gt; f.name === &#039;novaRelatorioDados&#039;);

if (novaFeature?.enabled) {

return &lt;NovoRelatorioDados /&gt;;

}

return &lt;RelatorioDadosLegado /&gt;;

}

export default ReleasePage;</code></pre>

<h2>Rollouts Graduais: Estratégia e Implementação</h2>

<p>Um dos maiores benefícios dos feature flags é permitir rollouts graduais — liberar uma feature para 1% dos usuários, depois 5%, depois 25%, até 100%. Isso minimiza riscos e permite capturar bugs antes de afetar todos.</p>

<h3>Estratégia de Rollout Seguro</h3>

<p>A abordagem recomendada é começar muito pequeno. Com LaunchDarkly, você pode ativar um flag para um pequeno percentual e observar métricas:</p>

<ol>

<li><strong>Lançar para 1-5% dos usuários</strong>: Monitore erros, latência, comportamento.</li>

<li><strong>Expandir para 10-25% se tudo bem</strong>: Continue observando dados de telemetria.</li>

<li><strong>Ativar para 50-100% gradualmente</strong>: Se não houver problemas, libere para todos.</li>

<li><strong>Manter o flag ligado ou remover</strong>: Depois de estável, você pode remover o flag do código ou deixá-lo como fail-safe permanente.</li>

</ol>

<h3>Implementação com Monitoramento</h3>

<p>Aqui está um exemplo real que integra rollout gradual com tratamento de erros:</p>

<pre><code class="language-jsx">import { useLDClient } from &#039;launchdarkly-react-client-sdk&#039;;

import { useEffect, useState } from &#039;react&#039;;

function CheckoutFlow() {

const ldClient = useLDClient();

const [paymentGateway, setPaymentGateway] = useState(null);

const [error, setError] = useState(null);

useEffect(() =&gt; {

const novoGatewayAtivado = ldClient.variation(

&#039;novoGatewayPagamento&#039;,

false

);

if (novoGatewayAtivado) {

// Tenta usar novo gateway

inicializarNovoGateway()

.catch(err =&gt; {

console.error(&#039;Novo gateway falhou:&#039;, err);

setError(err);

// Fallback para gateway antigo

setPaymentGateway(&#039;antigo&#039;);

})

.then(() =&gt; setPaymentGateway(&#039;novo&#039;));

} else {

setPaymentGateway(&#039;antigo&#039;);

}

}, [ldClient]);

if (error &amp;&amp; paymentGateway === &#039;antigo&#039;) {

return &lt;GatewayPagamentoAntigo /&gt;;

}

if (paymentGateway === &#039;novo&#039;) {

return &lt;NovoGatewayPagamento /&gt;;

}

if (paymentGateway === &#039;antigo&#039;) {

return &lt;GatewayPagamentoAntigo /&gt;;

}

return &lt;div&gt;Carregando...&lt;/div&gt;;

}

async function inicializarNovoGateway() {

// Simulando inicialização do novo gateway

return new Promise((resolve, reject) =&gt; {

setTimeout(() =&gt; resolve(&#039;gateway inicializado&#039;), 500);

});

}

export default CheckoutFlow;</code></pre>

<h3>Rastreando Conversões com Flags</h3>

<p>É importante capturar dados sobre qual versão o usuário viu, para análise posterior:</p>

<pre><code class="language-jsx">import { useLDClient } from &#039;launchdarkly-react-client-sdk&#039;;

import { useEffect } from &#039;react&#039;;

function CheckoutSuccess() {

const ldClient = useLDClient();

useEffect(() =&gt; {

const variacaoUsada = ldClient.variation(&#039;checkoutFlow&#039;, &#039;controle&#039;);

// Enviar para seu analytics

window.analytics?.track(&#039;checkout_completed&#039;, {

variacao: variacaoUsada,

timestamp: new Date().toISOString()

});

}, [ldClient]);

return &lt;div&gt;Pedido realizado com sucesso!&lt;/div&gt;;

}

export default CheckoutSuccess;</code></pre>

<h2>Comparação Prática: LaunchDarkly vs Unleash</h2>

<p>Ambas as plataformas fazem a mesma coisa, mas com trade-offs diferentes:</p>

<div class="table-wrap"><table><thead><tr><th>Aspecto</th><th>LaunchDarkly</th><th>Unleash</th></tr></thead><tbody><tr><td><strong>Modelo</strong></td><td>SaaS (nuvem)</td><td>Open Source / Self-hosted</td></tr><tr><td><strong>Custo</strong></td><td>Pago (enterprise)</td><td>Gratuito</td></tr><tr><td><strong>Setup</strong></td><td>Minutos</td><td>Horas (setup do servidor)</td></tr><tr><td><strong>Painel UI</strong></td><td>Muito polido</td><td>Funcional, menos polido</td></tr><tr><td><strong>Integrações</strong></td><td>Amplas (Slack, Datadog, etc)</td><td>Limitadas</td></tr><tr><td><strong>Segurança</strong></td><td>Enterprise-grade</td><td>Você controla</td></tr><tr><td><strong>Escalabilidade</strong></td><td>Gerenciada (SaaS)</td><td>Você gerencia</td></tr></tbody></table></div>

<p><strong>Use LaunchDarkly</strong> se: você quer algo pronto, suporte profissional e não se importa com custo.</p>

<p><strong>Use Unleash</strong> se: você quer controle total, está disposto a fazer setup/manutenção ou tem restrições de dados/conformidade.</p>

<h2>Conclusão</h2>

<p>Aprendemos que <strong>feature flags não são apenas um recurso técnico, são uma mudança de filosofia</strong> na entrega de software. Você passa de &quot;pronto para soltar para todos&quot; para &quot;controlar quem vê o quê em tempo real&quot;, eliminando a pressão de releases perfeitas e permitindo experimentos seguros.</p>

<p>Em segundo lugar, <strong>LaunchDarkly e Unleash servem a propósitos similares com abordagens diferentes</strong> — um é conveniente e gerenciado, o outro oferece liberdade e controle. A escolha depende de seus requisitos de infraestrutura, conformidade e orçamento. Ambas têm SDKs excelentes para React e permitem implementar rollouts graduais com pouquíssimo esforço.</p>

<p>Por fim, <strong>um rollout gradual bem executado reduz drasticamente o risco de um bug em produção se tornar um desastre</strong>. Começando pequeno (1-5%), monitorando métricas, e expandindo só quando tudo estiver bem, você ganha confiança e dados reais antes de expor a feature a todos. Isso é engenharia real de software.</p>

<h2>Referências</h2>

<ul>

<li><a href="https://docs.launchdarkly.com/sdk/client-side/react" target="_blank" rel="noopener noreferrer">LaunchDarkly React SDK Documentation</a></li>

<li><a href="https://docs.getunleash.io/" target="_blank" rel="noopener noreferrer">Unleash Official Documentation</a></li>

<li><a href="https://martinfowler.com/articles/feature-toggles.html" target="_blank" rel="noopener noreferrer">Feature Toggles (Martin Fowler)</a></li>

<li><a href="https://launchdarkly.com/blog/best-practices-for-feature-flags/" target="_blank" rel="noopener noreferrer">Best Practices for Feature Flags</a></li>

<li><a href="https://github.com/Unleash/unleash" target="_blank" rel="noopener noreferrer">Unleash GitHub Repository</a></li>

</ul>

<p>&lt;!-- FIM --&gt;</p>

Comentários

Mais em React & Frontend

Internacionalização em React: react-i18next e Formatação de Dados na Prática
Internacionalização em React: react-i18next e Formatação de Dados na Prática

Entendendo Internacionalização em Aplicações React Internacionalização (i18n)...

useMemo e useCallback: Memoização Real com Análise de Custo na Prática
useMemo e useCallback: Memoização Real com Análise de Custo na Prática

Entendendo Memoização em React Memoização é uma técnica de otimização que con...

Upload de Arquivos em React: Preview, Progress e Validação de Tipo na Prática
Upload de Arquivos em React: Preview, Progress e Validação de Tipo na Prática

Upload de Arquivos em React: Fundamentos e Arquitetura Upload de arquivos é u...