Feature flags e progressive delivery em aplicativos
Lançar uma nova funcionalidade em produção é um momento de tensão: quanto mais usuários, maior o risco de algo quebrar para todo mundo ao mesmo tempo. Progressive delivery e feature flags surgiram para resolver exatamente isso — permitir que você implante código sem expor todos os usuários de uma vez, teste em produção de forma controlada e reverta mudanças instantaneamente se algo der errado.
Esse modelo é especialmente útil para aplicativos móveis e sistemas web que não podem parar. Neste guia, você vai entender o que são feature flags, como progressive delivery funciona na prática, quando vale a pena implementar e quais riscos evitar.
O que são feature flags
Feature flags (ou feature toggles) são interruptores no código que controlam se uma funcionalidade está ativa ou não. Em vez de condicionar o comportamento do app ao deploy, você condiciona a uma variável de configuração que pode ser alterada remotamente.
Exemplo simplificado:
```javascript
if (featureFlags.newCheckoutFlow) {
renderNewCheckout();
} else {
renderOldCheckout();
}
```
Essa flag pode ser gerenciada por um serviço externo (LaunchDarkly, Firebase Remote Config, Unleash, Split.io) ou por uma tabela interna do sistema. O valor é consultado em tempo de execução, o que permite ativar ou desativar features sem publicar uma nova versão do aplicativo.
Feature flags não são gambiarras técnicas — são arquitetura de entrega quando bem aplicadas. Empresas como Facebook, Google, Netflix e Amazon usam flags há anos para controlar o rollout de funcionalidades críticas.
Diferença entre feature flags e progressive delivery
Feature flags são a técnica: o interruptor no código que controla se uma funcionalidade está ativa.
Progressive delivery é a estratégia: usar feature flags para implantar código em produção de forma gradual e controlada, monitorando o impacto antes de liberar para 100% dos usuários.
Um exemplo de progressive delivery:
- Deploy do código com a nova funcionalidade desativada por padrão (flag = false).
- Ativação para 5% dos usuários.
- Monitoramento de métricas (crash rate, tempo de resposta, conversão).
- Se tudo estiver estável, aumento para 25%, depois 50%, depois 100%.
- Se houver problema, reversão imediata mudando a flag para false — sem precisar fazer rollback de código.
Isso é diferente de canary deployment tradicional (que trabalha com versões diferentes da infraestrutura) e de A/B testing puro (que compara variantes, mas nem sempre controla o rollout progressivo).
Tipos de feature flags
Nem todo feature flag serve para o mesmo propósito. É importante classificá-los para evitar que flags temporárias virem dívida técnica permanente.
1. Release flags (flags de lançamento)
Objetivo: controlar o rollout de uma nova funcionalidade.
Vida útil: curta — devem ser removidas do código depois que a feature estiver 100% ativa e estável.
Exemplo: nova versão do fluxo de pagamento, redesign de tela, integração com novo provedor.
2. Ops flags (flags operacionais)
Objetivo: controlar comportamento em caso de incidente ou sobrecarga.
Vida útil: permanente — fazem parte da arquitetura de resiliência.
Exemplo: desativar envio de notificações push se a fila estiver congestionada; desabilitar sincronização pesada se o banco estiver lento.
3. Experiment flags (flags de experimento)
Objetivo: rodar testes A/B ou multivariados.
Vida útil: temporária — depois que o experimento termina e uma variante vence, a flag deve ser removida.
Exemplo: testar dois textos de CTA, duas variações de layout, dois fluxos de onboarding.
4. Permission flags (flags de permissão)
Objetivo: liberar funcionalidades para grupos específicos (beta testers, early adopters, clientes enterprise).
Vida útil: longa ou permanente — fazem parte do modelo de negócio ou da política de acesso.
Exemplo: acesso a recursos premium, versão beta de uma feature, modo administrativo.
Manter flags de release ativas por meses é um erro comum. O ideal é documentar cada flag com tipo, data de criação, responsável e critério de remoção.
Quando progressive delivery vale a pena
Nem todo app ou sistema precisa de progressive delivery. Implantá-la sem necessidade real adiciona complexidade operacional e pode dificultar a manutenção. Use quando:
- O app tem muitos usuários ativos e o impacto de um bug é alto. Se você tem milhares ou milhões de usuários, liberar uma feature quebrada para todos ao mesmo tempo pode gerar perda de receita, aumento de churn ou volume de suporte insustentável.
- O ciclo de aprovação na App Store ou Google Play demora demais para permitir rollback rápido. Se corrigir um bug exige publicar uma nova versão e esperar revisão manual (1 a 3 dias no iOS, algumas horas no Android), feature flags permitem reverter o problema em minutos apenas mudando uma configuração remota.
- Você quer validar o impacto de uma mudança antes de consolidá-la. Progressive delivery permite medir crash rate, tempo de carregamento, taxa de conversão e NPS antes de liberar para 100%. Se os indicadores piorarem, você reverte; se melhorarem, acelera o rollout.
- A funcionalidade é crítica e você não pode testar completamente em ambiente de homologação. Alguns comportamentos só aparecem em produção: volume real de dados, latência de rede variável, dispositivos antigos, integrações com sistemas de terceiros. Liberar para 1% primeiro reduz o raio de impacto de bugs não detectados.
- Você precisa alinhar o lançamento com marketing, parceiros ou eventos externos. Com feature flags, o código vai para produção dias antes, mas a funcionalidade só é ativada na hora exata do anúncio — sem depender de horário de deploy.
Progressive delivery não vale a pena quando:
- O app tem poucos usuários ou o custo de um bug é baixo (ex: app interno de 50 pessoas).
- A funcionalidade não tem impacto significativo (ex: ajuste de cor de botão).
- O time não tem capacidade de monitorar métricas durante o rollout (se você não olha os números, a flag não serve para nada).
- A complexidade técnica de manter flags supera o benefício (ex: código legado sem testes automatizados, impossível isolar a funcionalidade).
Como implementar feature flags em aplicativos móveis
A implementação básica de feature flags envolve três camadas: gerenciamento remoto, cache local e código condicionado.
1. Escolha de ferramenta
Opções populares:
- Firebase Remote Config (grátis, integrado ao Firebase, boa para apps mobile)
- LaunchDarkly (pago, robusto, com targeting avançado e métricas integradas)
- Split.io (pago, foco em feature delivery e experimentação)
- Unleash (open-source, self-hosted ou cloud)
- ConfigCat (pago, simples e leve)
Para MVPs e apps menores, Firebase Remote Config geralmente é suficiente. Para produtos com alta escala ou necessidade de targeting complexo (flags por versão do app, por região, por segmento de usuário), ferramentas especializadas como LaunchDarkly oferecem mais controle.
2. Sincronização e cache
Feature flags devem ser sincronizadas no momento certo:
- No início da sessão (ao abrir o app)
- Em intervalos periódicos (a cada 15 minutos, por exemplo)
- Após eventos específicos (login, mudança de tela crítica)
O app deve armazenar as flags localmente (cache) para funcionar offline. Se a sincronização falhar, o app usa o último valor conhecido. Defina um fallback padrão no código para quando não há valor em cache — geralmente, o comportamento mais seguro é manter a funcionalidade desativada.
3. Estrutura no código
Organize flags por contexto:
```javascript
const flags = {
features: {
newCheckoutFlow: false,
darkMode: true,
referralProgram: false,
},
ops: {
enablePushNotifications: true,
enableHeavySync: true,
},
experiments: {
abTestCheckoutButton: 'variant_a',
},
};
```
Evite espalhar `if (flag)` direto no código. Centralize a lógica de decisão em funções ou serviços:
```javascript
function shouldShowNewCheckout(user) {
return flags.features.newCheckoutFlow && user.isPremium;
}
```
Isso facilita testes, manutenção e remoção futura da flag.
4. Targeting e segmentação
Feature flags ficam mais poderosas quando combinadas com segmentação:
- Liberar apenas para usuários de uma versão específica do app (ex: >= 2.5.0).
- Liberar apenas para um país ou região (ex: Brasil).
- Liberar apenas para um percentual aleatório de usuários (ex: 10%).
- Liberar apenas para usuários que já fizeram uma compra.
Ferramentas como LaunchDarkly, Split e Unleash oferecem targeting nativo. No Firebase Remote Config, você precisa implementar a lógica manualmente combinando conditions e user properties.
Estratégia de rollout progressivo
A progressão típica de um rollout controlado:
- Deploy com flag desativada — código vai para produção, mas ninguém vê a feature.
- Ativação para equipe interna — desenvolvedores e QA testam em produção.
- Ativação para 1% a 5% — primeiros usuários reais; observe crash rate, performance, feedback.
- Aumento para 25% — se métricas estiverem estáveis.
- Aumento para 50% — validação de volume médio.
- Ativação para 100% — rollout completo.
- Remoção da flag do código — depois que a feature estiver consolidada e estável por algumas semanas.
Cada etapa deve durar o tempo necessário para coletar dados significativos. Para features críticas, espere pelo menos 24h em cada etapa. Para features de baixo risco, você pode acelerar.
Monitore:
- Crash rate (taxa de travamento do app)
- Tempo de resposta (latência de telas e APIs)
- Taxa de conversão (se a feature impacta fluxos de receita)
- Feedback de usuários (comentários, suporte, avaliações na loja)
Se qualquer métrica piorar de forma significativa, pause o rollout, investigue e, se necessário, reverta.
Riscos e dívida técnica de feature flags
Feature flags mal gerenciadas viram passivo técnico. Riscos comuns:
1. Flags abandonadas
Flags de release que nunca foram removidas do código acumulam-se, tornando o sistema mais difícil de entender e testar. Depois de 6 meses, ninguém mais sabe por que a flag existe ou se é seguro removê-la.
Como evitar: documente cada flag com data de criação, responsável, objetivo e critério de remoção. Revise flags mensalmente. Crie alertas automáticos para flags com mais de 90 dias sem mudança.
2. Explosão combinatória de estados
Cada flag adiciona 2 estados possíveis ao sistema. Com 5 flags, você tem 32 combinações. Com 10, são 1.024. Testar todas as combinações é inviável.
Como evitar: limite o número de flags ativas simultaneamente. Remova flags antigas antes de criar novas. Para features interdependentes, use uma flag master que controla o grupo todo em vez de flags independentes.
3. Flags permanentes sem governança
Ops flags e permission flags são úteis, mas se não houver controle de quem pode mudar uma flag e quando, o sistema pode entrar em estado inconsistente.
Como evitar: defina permissões de acesso. Use logs de auditoria para registrar quem mudou uma flag e quando. Em produção, exija aprovação de mais de uma pessoa para mudar flags críticas.
4. Dependência excessiva de serviços externos
Se as flags são gerenciadas por um serviço externo e ele cai, o app pode se comportar de forma inesperada.
Como evitar: sempre tenha cache local e fallback padrão. Teste o comportamento do app quando o serviço de flags está indisponível.
Progressive delivery vs A/B testing
Progressive delivery e A/B testing são complementares, mas servem propósitos diferentes.
Progressive delivery controla o rollout de uma mudança para minimizar risco. Você assume que a nova versão é melhor e vai liberá-la progressivamente até 100%.
A/B testing compara duas ou mais variantes para descobrir qual performa melhor. Você não sabe qual versão é superior até o experimento terminar.
É possível combinar os dois: rodar um A/B test com progressive delivery — liberar a variante vencedora de forma gradual depois que o experimento validou que ela é melhor.
Ferramentas como LaunchDarkly, Split e Optimizely permitem configurar experimentos dentro do mesmo sistema de feature flags.
Ferramentas e integrações
Firebase Remote Config
Prós: grátis, fácil de integrar, funciona bem com apps mobile.
Contras: targeting limitado, sem métricas integradas, interface básica.
Melhor para: MVPs, apps pequenos e médios, quem já usa Firebase.
LaunchDarkly
Prós: targeting avançado, métricas integradas, auditoria completa, suporte multi-plataforma.
Contras: caro para alto volume de usuários.
Melhor para: produtos enterprise, apps críticos com muitos usuários.
Split.io
Prós: foco em experimentação, métricas de impacto, boa UX.
Contras: pricing baseado em volume de eventos.
Melhor para: produtos que rodam muitos experimentos e precisam de dados detalhados.
Unleash
Prós: open-source, self-hosted, sem custo de licença, API flexível.
Contras: requer infraestrutura própria, menos recursos out-of-the-box que ferramentas pagas.
Melhor para: empresas que preferem controle total e já têm infraestrutura para hospedar.
Independentemente da ferramenta, integre feature flags ao sistema de observabilidade (Datadog, New Relic, Sentry) para correlacionar mudanças de flags com variações de métricas.
Ciclo de vida de uma feature flag
Para evitar que flags virem dívida técnica, defina um ciclo de vida claro:
- Criação — documente tipo (release, ops, experiment, permission), responsável, objetivo, critério de remoção.
- Rollout — ative progressivamente, monitore métricas, pause ou reverta se necessário.
- Consolidação — quando a feature estiver 100% ativa e estável por pelo menos 2 semanas, agende a remoção da flag.
- Remoção — elimine o código condicional, deixe apenas o comportamento final. Teste que a remoção não quebrou nada.
- Deploy da remoção — publique a versão limpa do código.
Flags de release devem viver semanas, não meses. Flags operacionais e de permissão podem ser permanentes, mas devem ser revisadas a cada trimestre para garantir que ainda fazem sentido.
Como estruturar o código para facilitar a remoção de flags
Flags temporárias devem ser fáceis de remover. Organize o código para minimizar o impacto da remoção:
Ruim:
```javascript
function checkout() {
if (flags.newCheckout) {
// 150 linhas de código inline
} else {
// 100 linhas de código inline
}
}
```
Remover a flag aqui exige editar uma função gigante.
Melhor:
```javascript
function checkout() {
if (flags.newCheckout) {
return newCheckoutFlow();
} else {
return oldCheckoutFlow();
}
}
```
Quando a flag for removida, basta deletar a condicional e manter `newCheckoutFlow()`.
Ainda melhor:
```javascript
function checkout() {
const flow = featureService.getCheckoutFlow();
return flow.execute();
}
```
A decisão de qual fluxo usar está centralizada no `featureService`. Remover a flag significa editar um único ponto.
Progressive delivery em aplicativos nativos vs web
Apps nativos (iOS, Android) têm limitações que apps web não têm:
- Não dá para fazer rollback instantâneo de código — reversão depende de publicar nova versão e esperar aprovação da loja.
- Usuários podem estar em versões antigas do app — você precisa gerenciar flags entre múltiplas versões publicadas.
- Cache e sincronização de flags precisam funcionar offline — diferente de web, onde cada acesso busca o valor mais recente.
Por isso, feature flags são ainda mais valiosas em apps mobile: elas contornam a limitação do ciclo de aprovação das lojas.
No entanto, flags em apps mobile devem ser mais conservadoras:
- Evite mudar comportamento crítico via flag em versões antigas do app (pode gerar inconsistência).
- Sempre teste o comportamento do app quando a flag está offline ou dessincronizada.
- Documente qual versão mínima do app cada flag suporta.
Casos de uso reais
Caso 1: redesign de tela crítica
Problema: a tela de checkout será completamente redesenhada. Se houver bug, pode impactar conversão.
Solução: deploy da nova tela com flag desativada. Ativação para 5% dos usuários. Monitoramento de taxa de conversão e crash rate. Aumento progressivo até 100%. Depois de 2 semanas sem incidentes, remoção da flag e do código antigo.
Resultado: redesign lançado sem impacto negativo. Um bug menor detectado na fase de 5% foi corrigido antes de chegar a 100% dos usuários.
Caso 2: integração com provedor de pagamento
Problema: novo provedor de pagamento será integrado, mas não há certeza se ele vai funcionar bem sob carga real.
Solução: flag operacional que redireciona 10% das transações para o novo provedor. Monitoramento de taxa de aprovação, latência e erros. Aumento gradual. Flag mantida permanentemente para permitir fallback rápido em caso de instabilidade futura do provedor.
Resultado: integração validada em produção de forma controlada. Flag virou parte da arquitetura de resiliência.
Caso 3: funcionalidade para beta testers
Problema: nova funcionalidade será lançada em versão beta antes de ir para o público geral.
Solução: permission flag ativada apenas para usuários marcados como beta testers. Feedback coletado durante 3 semanas. Ajustes feitos. Depois, liberação progressiva para o público geral. Remoção da flag quando 100% dos usuários tiverem acesso.
Resultado: bugs identificados e corrigidos antes do lançamento público.
Governança e cultura de feature flags
Para que progressive delivery funcione, o time precisa de disciplina:
- Revise flags ativas mensalmente. Flags antigas que ninguém mais mexe devem ser removidas.
- Documente flags no mesmo lugar. Use um wiki, Notion ou a própria ferramenta de flags para manter documentação centralizada.
- Defina dono de cada flag. Alguém deve ser responsável por monitorar o rollout e decidir quando remover.
- Integre flags ao processo de code review. Code review deve incluir verificação de que a flag tem documentação, tipo, e plano de remoção.
- Automatize a detecção de flags antigas. Crie scripts que alertem quando uma flag tem mais de 90 dias sem mudança.
Flags são código. Devem ser tratadas com o mesmo rigor que qualquer outra parte do sistema.
Perguntas frequentes
Progressive delivery funciona para apps pequenos?
Sim, mas o custo-benefício é menor. Se o app tem poucos usuários, o impacto de um bug é baixo e o ciclo de correção é rápido, feature flags podem adicionar complexidade desnecessária. Progressive delivery faz mais sentido quando o custo de erro é alto (muitos usuários, fluxo crítico de receita, dependência de aprovação de loja).
Quanto custa implementar feature flags?
Depende da ferramenta. Firebase Remote Config é grátis. LaunchDarkly começa em centenas de dólares por mês para produtos menores e pode chegar a milhares em alta escala. Unleash é open-source, mas exige custo de infraestrutura e manutenção. Para a maioria dos apps, o custo de tooling é menor do que o custo de um incidente causado por um rollout mal planejado.
Como garantir que flags não virem dívida técnica?
Defina um ciclo de vida claro: toda flag de release deve ter data de criação, responsável, objetivo e critério de remoção. Revise flags mensalmente. Automatize alertas para flags com mais de 90 dias sem mudança. Remova flags assim que a feature estiver consolidada. Flags permanentes (ops, permission) devem ser exceção, não regra.
Conclusão
Progressive delivery e feature flags são estratégias para reduzir o risco de mudanças em produção. Permitem que você implante código de forma gradual, monitore o impacto, reverta rapidamente se algo der errado e teste em produção de forma controlada.
São especialmente úteis em aplicativos móveis, onde o ciclo de aprovação das lojas torna rollback de código lento e custoso. Implementar feature flags não exige refatoração completa — você pode começar com uma ferramenta simples como Firebase Remote Config e evoluir conforme a necessidade.
O risco real não está na técnica, mas na falta de governança: flags abandonadas viram dívida técnica, e flags mal gerenciadas tornam o sistema mais complexo de entender e testar. Para que progressive delivery funcione, o time precisa de disciplina: documentar flags, revisar periodicamente, remover quando não são mais necessárias e integrar flags ao processo de code review.
Se o seu aplicativo já tem muitos usuários, fluxos críticos de receita ou histórico de incidentes causados por mudanças em produção, progressive delivery pode ser o próximo passo para entregar valor com mais segurança e controle.
Precisa de apoio para estruturar o desenvolvimento de aplicativos com arquitetura preparada para evolução contínua, feature flags e ciclos de deploy mais seguros? A Clicksoft desenvolve apps, sistemas e produtos digitais sob medida, com foco em qualidade, escalabilidade e governança técnica desde o primeiro deploy. Entre em contato e vamos conversar sobre o seu projeto.