Pular para conteúdo

FEATURE_FLAG - Feature Flags e Progressive Rollout

O que é este Node?

O FEATURE_FLAG é o node responsável por controlar lançamento de features via flags, permitindo ativar/desativar funcionalidades sem deploy, fazer progressive rollout e A/B testing.

Por que este Node existe?

Feature flags separam deploy de release. O FEATURE_FLAG existe para:

  1. Decouple Deploy from Release: Deploy código desativado, ativa depois
  2. Progressive Rollout: Libera para 1%, 10%, 50%, 100% gradualmente
  3. Kill Switch: Desativa feature rapidamente se houver problema
  4. A/B Testing: Testa features com grupos específicos
  5. Canary Releases: Testa com usuários internos primeiro

Como funciona internamente?

FEATURE_FLAG verifica se feature está ativa para usuário específico baseado em regras (% rollout, whitelist, cohorts).

Quando você DEVE usar este Node?

Use FEATURE_FLAG para lançamento controlado de features:

Casos de uso

  1. New Features: Lança gradualmente para reduzir risco
  2. Experimental Features: Testa com subset de usuários
  3. Beta Access: Libera para early adopters
  4. Premium Features: Ativa apenas para pagantes
  5. Emergency Killswitch: Desativa rapidamente se problema

Quando NÃO usar FEATURE_FLAG

  • Features simples: Overhead desnecessário
  • Hot Fixes: Deploy direto é mais rápido
  • Features permanentes: Remove flag após rollout completo

Parâmetros Detalhados

flagName (string, obrigatório)

O que é: Nome único da feature flag.

enabled (boolean, obrigatório)

O que é: Se feature está ativa globalmente.

rolloutPercentage (number, opcional)

O que é: % de usuários que vêem feature (0-100).

Flow completo para testar:**

{
  "name": "Feature Flag - Progressive Rollout",
  "nodes": [
    {
      "id": "start_1",
      "type": "start",
      "position": { "x": 100, "y": 100 },
      "data": { "label": "Início" }
    },
    {
      "id": "variable_1",
      "type": "variable",
      "position": { "x": 300, "y": 100 },
      "data": {
        "label": "Check Flag",
        "parameters": {
          "name": "feature_enabled",
          "value": "{{$random([true, true, false, false])}}"
        }
      }
    },
    {
      "id": "analytics_1",
      "type": "analytics",
      "position": { "x": 500, "y": 100 },
      "data": {
        "label": "Track Flag Check",
        "parameters": {
          "eventName": "feature_flag_checked",
          "properties": {
            "flag_name": "ai_assistant_v2",
            "enabled": "{{feature_enabled}}",
            "rollout_percentage": 50
          }
        }
      }
    },
    {
      "id": "condition_1",
      "type": "condition",
      "position": { "x": 700, "y": 100 },
      "data": {
        "label": "Is Enabled?",
        "parameters": {
          "variable": "feature_enabled",
          "operator": "equals",
          "value": true
        }
      }
    },
    {
      "id": "message_1",
      "type": "message",
      "position": { "x": 900, "y": 50 },
      "data": {
        "label": "New Feature",
        "parameters": {
          "message": "🚀 Você tem acesso à nova feature!\n\nAssistente com processamento avançado v2.0"
        }
      }
    },
    {
      "id": "message_2",
      "type": "message",
      "position": { "x": 900, "y": 150 },
      "data": {
        "label": "Old Feature",
        "parameters": {
          "message": "📱 Assistente padrão v1.0"
        }
      }
    },
    {
      "id": "analytics_2",
      "type": "analytics",
      "position": { "x": 1100, "y": 50 },
      "data": {
        "label": "Track Feature Used",
        "parameters": {
          "eventName": "feature_used",
          "properties": {
            "feature_name": "ai_assistant_v2",
            "version": "2.0"
          }
        }
      }
    },
    {
      "id": "message_3",
      "type": "message",
      "position": { "x": 1300, "y": 100 },
      "data": {
        "label": "Result",
        "parameters": {
          "message": "✅ Feature flag verificada!\n\nStatus: {{feature_enabled}}"
        }
      }
    },
    {
      "id": "end_1",
      "type": "end",
      "position": { "x": 1500, "y": 100 },
      "data": { "label": "Fim" }
    }
  ],
  "edges": [
    { "source": "start_1", "target": "variable_1" },
    { "source": "variable_1", "target": "analytics_1" },
    { "source": "analytics_1", "target": "condition_1" },
    { "source": "condition_1", "target": "message_1", "label": "true" },
    { "source": "condition_1", "target": "message_2", "label": "false" },
    { "source": "message_1", "target": "analytics_2" },
    { "source": "analytics_2", "target": "message_3" },
    { "source": "message_2", "target": "message_3" },
    { "source": "message_3", "target": "end_1" }
  ]
}

Teste: Execute múltiplas vezes. ~50% vê feature nova, ~50% vê feature antiga.

Parâmetros

Campo Tipo Obrigatório Descrição
flagName string Sim Nome único da flag
enabled boolean Sim Se feature está ativa
rolloutPercentage number Não % de usuários (0-100)
whitelist array Não User IDs com acesso garantido
blacklist array Não User IDs bloqueados
cohorts array Não Cohorts com acesso

Exemplo: Canary Release

Objetivo: Lançar feature primeiro para funcionários, depois 10%, depois 100%.

{
  "name": "Feature Flag - Canary Release",
  "nodes": [
    {
      "id": "start_1",
      "type": "start",
      "position": { "x": 100, "y": 100 },
      "data": { "label": "Início" }
    },
    {
      "id": "input_1",
      "type": "input",
      "position": { "x": 300, "y": 100 },
      "data": {
        "label": "Get User Email",
        "parameters": {
          "message": "Digite seu email",
          "variable": "user_email"
        }
      }
    },
    {
      "id": "variable_1",
      "type": "variable",
      "position": { "x": 500, "y": 100 },
      "data": {
        "label": "Check Whitelist",
        "parameters": {
          "name": "is_internal",
          "value": "{{user_email.includes('@empresa.com')}}"
        }
      }
    },
    {
      "id": "condition_1",
      "type": "condition",
      "position": { "x": 700, "y": 100 },
      "data": {
        "label": "Internal User?",
        "parameters": {
          "variable": "is_internal",
          "operator": "equals",
          "value": true
        }
      }
    },
    {
      "id": "message_1",
      "type": "message",
      "position": { "x": 900, "y": 50 },
      "data": {
        "label": "Internal Access",
        "parameters": {
          "message": "🚀 CANARY RELEASE\n\nVocê está no grupo interno com acesso prioritário à nova feature!"
        }
      }
    },
    {
      "id": "variable_2",
      "type": "variable",
      "position": { "x": 900, "y": 150 },
      "data": {
        "label": "10% Rollout",
        "parameters": {
          "name": "in_rollout",
          "value": "{{$random([true, false, false, false, false, false, false, false, false, false])}}"
        }
      }
    },
    {
      "id": "analytics_1",
      "type": "analytics",
      "position": { "x": 1100, "y": 100 },
      "data": {
        "label": "Track Flag Status",
        "parameters": {
          "eventName": "feature_flag_evaluated",
          "properties": {
            "flag_name": "new_dashboard",
            "user_email": "{{user_email}}",
            "is_internal": "{{is_internal}}",
            "in_rollout": "{{in_rollout}}",
            "access_granted": true
          }
        }
      }
    },
    {
      "id": "message_2",
      "type": "message",
      "position": { "x": 1300, "y": 100 },
      "data": {
        "label": "Confirmation",
        "parameters": {
          "message": "✅ Feature flag avaliada!\n\nEmail: {{user_email}}\nInterno: {{is_internal}}\nAcesso: Liberado"
        }
      }
    },
    {
      "id": "end_1",
      "type": "end",
      "position": { "x": 1500, "y": 100 },
      "data": { "label": "Fim" }
    }
  ],
  "edges": [
    { "source": "start_1", "target": "input_1" },
    { "source": "input_1", "target": "variable_1" },
    { "source": "variable_1", "target": "condition_1" },
    { "source": "condition_1", "target": "message_1", "label": "true" },
    { "source": "condition_1", "target": "variable_2", "label": "false" },
    { "source": "message_1", "target": "analytics_1" },
    { "source": "variable_2", "target": "analytics_1" },
    { "source": "analytics_1", "target": "message_2" },
    { "source": "message_2", "target": "end_1" }
  ]
}

Resposta do Node

{
  "success": true,
  "action": "feature_flag_evaluated",
  "flagName": "new_dashboard",
  "enabled": true,
  "rolloutPercentage": 10,
  "userAccess": true,
  "timestamp": "2025-01-15T10:30:00.000Z"
}

Rollout Strategy

Phase 1: Internal (0-1%)

  • Apenas funcionários
  • Testa em produção com baixo risco
  • Fix bugs críticos

Phase 2: Early Adopters (1-10%)

  • Beta testers, power users
  • Coleta feedback qualitativo
  • Monitora métricas

Phase 3: Wider Rollout (10-50%)

  • Aumento gradual
  • Monitora performance e erros
  • Compara com grupo de controle

Phase 4: Full Rollout (100%)

  • Todos os usuários
  • Remove feature flag após estabilizar

Ferramentas de Feature Flags

LaunchDarkly

Enterprise feature flag management

Split.io

Feature flags + A/B testing

Unleash

Open-source feature flags

PostHog

Analytics + feature flags integrado

Boas Práticas

SIM: - Comece com rollout pequeno (1-5%) - Monitore métricas chave durante rollout - Tenha kill switch pronto - Remove flags após feature estável - Use flags para A/B testing

NÃO: - Não deixe flags antigas no código (technical debt) - Não role out 100% imediatamente - Não esqueça de monitorar erros durante rollout

Dicas

💡 Dica 1: Use feature flags para trunk-based development 💡 Dica 2: Combine com AB_TEST para experimentos 💡 Dica 3: Monitore flag checks para entender uso 💡 Dica 4: Crie dashboard de flags ativas 💡 Dica 5: Automatic cleanup de flags antigas (>90 dias)

Próximo Node

USER_PROPERTIES - User properties tracking → AB_TEST - A/B testing → COHORT - Cohort analysis