Sistema de Feature Flags — Documentação Técnica
Documentação em construção. Público-alvo: devs do time (uso técnico/API).
Sistema avançado: rollout percentual, segmentação de usuários e A/B test.
Índice
- Visão geral
- Core de flags
- Targeting e segmentação
- Rollout progressivo
- A/B testing / Experimentação
- SDKs e integração técnica
- Autenticação (SDK Key)
- Sincronização em tempo real
- Eventos de conexão
- Webhooks (integração externa)
Visão geral
Sistema de feature flags construído do zero, com suporte a:
- Flags booleanas e multivariáveis
- Segmentação por atributos de usuário
- Rollout percentual com bucketing consistente
- A/B testing com múltiplas variantes
- SDKs client-side e server-side
Core de flags
- Tipos de flag: boolean (on/off) e multivariável (string/número/JSON), permitindo retornar variantes diferentes, não só ligar/desligar
- Ambientes: dev, staging, produção — cada um com seu próprio estado de flag
- Kill switch: desligar uma flag instantaneamente em produção, sem deploy
Targeting e segmentação
- Regras de segmentação: por atributo do usuário (país, plano, versão do app, device, etc.)
- Targeting individual: ligar a flag para usuários específicos (por ID, email)
- Grupos/coortes: listas de usuários (ex: beta testers, funcionários internos)
Rollout progressivo
- Rollout percentual: liberar gradualmente para uma fatia da base (5%, 10%, 50%...)
- Sticky bucketing: garante que o mesmo usuário sempre caia na mesma variante entre sessões
-
Hash consistente: normalmente hash do
user ID + flag keypara decidir o bucket
A/B testing / Experimentação
- Múltiplas variantes com pesos configuráveis (ex: A 33%, B 33%, C 34%)
- Integração com analytics: disparar eventos de exposição (quem viu qual variante)
- Significância estatística geralmente delegada a uma ferramenta de análise externa, mas o sistema de flags precisa expor os dados de exposição
SDKs e integração técnica
SDK client-side vs server-side
A diferença não é só "onde roda o código" — é uma questão de segurança e vazamento de informação.
Server-side SDK
- Roda em ambiente confiável (backend)
- Pode ter acesso a todas as flags, incluindo as não lançadas, regras de segmentação completas e segredos usados no targeting
- Comunica-se direto com a API central ou via um Relay Proxy (serviço intermediário que reduz chamadas repetidas)
Client-side SDK (browser, mobile, apps)
- Roda em ambiente não confiável — qualquer um pode inspecionar o payload
-
Nunca deve receber a lista completa de flags. O backend avalia a flag para aquele usuário específico e envia só o payload já resolvido (ex:
flag X = true,flag Y = variante B) - Isso é feito via endpoint do tipo
/sdk/eval?context={user}, retornando um payload minimalista - Regra crítica: nunca usar a SDK key server-side (completa) dentro de um app client — isso vazaria todas as flags e regras internas
Avaliação local vs remota
| Abordagem | Latência | Frescor dos dados |
|---|---|---|
| Remota (thin client) | Alta — chamada de rede a cada checagem | Sempre atualizado |
| Local (thick client, recomendada) | Baixa — avaliação em memória | Depende da estratégia de sync |
Estratégias de atualização do cache local:
- Polling: SDK pergunta "tem mudança?" a cada N segundos
- Streaming: servidor empurra updates em tempo real assim que uma flag muda
Muitos SDKs combinam os dois: streaming como canal principal + polling como fallback caso a conexão caia.
Fallback / default values
- Todo flag check exige um valor default obrigatório na chamada (nunca deixar o SDK "adivinhar")
-
Hierarquia de fallback:
- Valor em cache local (último snapshot conhecido)
- Se nunca conectou → default fornecido no código de chamada
- Falha do serviço de flags nunca deve travar a aplicação — deve ser silenciosa e logada
- Timeout de inicialização: tempo máximo de espera no boot para o primeiro fetch (ex: 5s); depois disso, segue com defaults e atualiza quando possível
- Emitir métrica/log quando o SDK cai em modo fallback, para sinalizar degradação do serviço
Autenticação (SDK Key)
A SDK key funciona como um bearer token:
Authorization: Bearer sdk-a1b2c3d4...
| Elemento | Papel |
|---|---|
| SDK key (bearer token) | Autentica + resolve escopo (projeto/ambiente) — não participa da decisão de segmentação |
| Context (key, plan, country...) | Fornece os dados para a decisão de segmentação e rollout |
Exemplo de request:
POST /evaluate
Headers: { "Authorization": "Bearer sdk-a1b2c3d4..." }
Body: {
"flagKey": "cancelar-nota-fiscal",
"context": {
"key": "user-12345",
"plan": "enterprise",
"country": "BR"
}
}
Por que não expor projectId/environment como parâmetros públicos
Alternativa descartada: passar ?project=app-mobile&env=production abertamente, sem token.
Problemas dessa abordagem:
- Enumeração — projectId previsível permite testar/descobrir outros projetos/ambientes
- Sem autenticação — impossível distinguir chamada legítima de bisbilhotagem
- Vazamento de lógica de negócio — testar contexts publicamente permite reconstruir regras de segmentação por engenharia reversa
- Sem revogação/rotação — sem token não há "chave" para cortar acesso; seria preciso mudar a própria estrutura da API
- Sem rate limiting/billing por cliente — impossível medir uso ou isolar consumidores
- DoS mais fácil — sem identificação, não dá para aplicar throttling seletivo
- Mistura acidental de ambientes — sem credencial vinculante, é mais fácil um client de produção acessar staging por engano
Sincronização em tempo real
Por que webhook não serve como mecanismo de sync do SDK
Webhook exige que o servidor inicie uma conexão de saída até o cliente — o que não funciona para a maioria dos consumidores reais de SDK:
- Frontend/browser: sem endereço público
- App mobile: sem IP público, sem porta aberta
- Backend atrás de NAT/firewall corporativo: porta não exposta
- Serverless/Lambda: função só existe durante a execução
- Múltiplas réplicas atrás de load balancer: ambíguo para qual réplica enviar
Por isso, o padrão adotado (como na maioria dos sistemas de feature flag do mercado) é o inverso: o cliente inicia a conexão de saída (streaming ou polling) e mantém ela aberta.
SSE como alternativa ao WebSocket
WebSocket é bidirecional e mais pesado que o necessário — o caso de uso aqui é apenas server → client.
SSE (Server-Sent Events) cobre esse caso:
- Conexão HTTP simples, unidirecional
- Reconexão automática nativa
- Funciona sobre HTTP/1.1 comum, sem upgrade de protocolo
- Mais simples de implementar mantendo tempo real
Eventos de conexão
SdkConnected
Dispara quando o SDK abre a conexão de streaming (SSE/WebSocket) e o token é validado com sucesso. Não é só "TCP conectou" — é "conexão autenticada e pronta para receber updates daquele escopo (org/app/ambiente)".
SdkDisconnected
Dispara quando a conexão cai, por um de três motivos (importante diferenciar no payload):
- Fechamento gracioso — shutdown, deploy, scale-down
- Timeout/heartbeat perdido — SDK parou de responder ao keep-alive
- Erro de rede — queda abrupta
Diferenciar o motivo importa para observabilidade: uma queda maciça de conexões pode ser "todo mundo fez deploy ao mesmo tempo" (normal) ou "o serviço de streaming caiu" (crítico).
Pontos de atenção:
- Reconexões automáticas com backoff podem gerar ruído (
SdkDisconnected → SdkConnectedrepetidos) — considerar debounce/agregação nas métricas - Incluir um
connectionIdúnico por sessão de streaming para correlacionar conexão/desconexão e calcular duração
Usos práticos:
- Observabilidade — quantos SDKs ativos por ambiente
- Detecção de degradação — queda anormal indica problema no Sync service
- Billing/capacity planning — se cobrança for por conexões simultâneas
Webhooks (integração externa)
Webhook não é o mecanismo de sincronização do SDK, mas é útil como feature de integração opcional, quando o receptor é um serviço backend do próprio cliente, controlado por eles, com endpoint público de propósito.
Exemplos de uso:
- Notificar o sistema de CI/CD do cliente quando uma flag mudar em produção
- Sincronizar com um sistema de config interno do cliente
Modelo proposto: URL de webhook registrada no momento da autenticação (junto com organização/aplicação/ambiente), salva em uma tabela de webhooks associada à chave/token.
Em aberto
- [ ] Detalhar payload dos eventos
SdkConnected/SdkDisconnected - [ ] Fluxo completo de
evaluate()(resolução de token → busca da flag → segmentação → rollout → resultado) - [ ] Desenho do schema de dados completo
- [ ] Desenho detalhado da tabela de webhooks como feature de integração
Top comments (0)