💻 Développement

dev-feature-flags-manager

Gestion de feature toggles avec LaunchDarkly, OpenFeature et implémentations custom pour le déploiement progressif et l'A/B testing.

⚡ Installation & lancement en 1 commande

Copiez-collez dans votre terminal : le skill s'installe dans ~/.claude/skills et Claude Code se lance directement dessus.

macOS / Linux
curl -fsSL https://raw.githubusercontent.com/khalilbenaz/claude-skills-collection/main/install.sh | sh -s -- dev-feature-flags-manager --launch
Windows (PowerShell)
iex "& { $(iwr -useb https://raw.githubusercontent.com/khalilbenaz/claude-skills-collection/main/install.ps1) } dev-feature-flags-manager -Launch"

🚀 Déjà installé ?

claude "/dev-feature-flags-manager"

Ou tapez /dev-feature-flags-manager dans une session Claude Code, ou décrivez simplement votre besoin — le skill se déclenche automatiquement via le skill-router.

🔑 Déclencheurs automatiques

Le skill s'active automatiquement quand votre demande contient :

LaunchDarklyOpenFeaturefeature toggledéploiement progressiffeature management .NETtoggles

📦 Installation manuelle

git clone https://github.com/khalilbenaz/claude-skills-collection.git cp -r claude-skills-collection/skills/dev-feature-flags-manager ~/.claude/skills/

Payload du plugin : skills/dev-feature-flags-manager · source éditable : dev-skills/feature-flags-manager

📖 Manuel

Feature Flags Manager

Workflow en étapes

  1. Choisir le type de flag (voir tableau de décision ci-dessous)
  2. Choisir le provider : Microsoft.FeatureManagement (simple, .NET natif) ou OpenFeature (multi-provider, standard industrie)
  3. Configurer le contexte d'évaluation : qui est l'utilisateur, quel environnement, quelles dimensions de ciblage
  4. Implémenter le flag avec fallback sûr et valeur par défaut explicite
  5. Tester les deux branches (flag ON et OFF) avant merge
  6. Définir la stratégie de rollout : % progressif, liste blanche, time window
  7. Monitorer : log chaque évaluation, alerter sur les anomalies de taux d'activation
  8. Nettoyer : supprimer le flag et le code conditionnel après adoption complète

Critères de décision : quel type de flag ?

BesoinTypeTTL conseillé
Activer une feature en prod sans redéploiementRelease toggle< 1 sprint
Rollout progressif (canary, blue/green)Percentage rollout< 2 semaines
A/B test avec métriquesExperiment toggleDurée de l'exp
Config différente par env/régionConfig toggleLong terme
Kill switch / circuit breakerOps togglePermanent

Règle clé : 1 feature = 1 flag. Ne jamais empiler plusieurs features sous un seul flag.

Choix du provider

CritèreMicrosoft.FeatureManagementLaunchDarkly (via OpenFeature)Unleash
CoûtGratuitPayant ($)Open source
Complexité setupMinimaleMoyenneMoyenne
Ciblage utilisateurBasique (Targeting filter)Avancé (segments, règles)Avancé
Evaluation server-sideOuiOuiOui
Multi-langage.NET uniquementMulti-SDKMulti-SDK
Dashboard UIAzure App ConfigLaunchDarkly consoleUnleash UI

Pour un projet .NET sans budget : Microsoft.FeatureManagement + Azure App Configuration. Pour un produit multi-équipes avec A/B testing poussé : LaunchDarkly via OpenFeature.


Microsoft Feature Management (.NET)

dotnet add package Microsoft.FeatureManagement.AspNetCore

Enregistrement

// Program.cs
builder.Services.AddFeatureManagement()
    .AddFeatureFilter<PercentageFilter>()
    .AddFeatureFilter<TimeWindowFilter>()
    .AddFeatureFilter<TargetingFilter>();

// Optionnel : depuis Azure App Configuration
builder.Configuration.AddAzureAppConfiguration(opts =>
    opts.Connect("<connection-string>")
        .UseFeatureFlags(ff => ff.CacheExpirationInterval = TimeSpan.FromSeconds(30)));

appsettings.json — patterns courants

{
  "FeatureManagement": {
    "SimpleFlag": true,

    "RolloutFlag": {
      "EnabledFor": [{
        "Name": "Percentage",
        "Parameters": { "Value": 10 }
      }]
    },

    "TargetedFlag": {
      "EnabledFor": [{
        "Name": "Targeting",
        "Parameters": {
          "Audience": {
            "Users": ["admin@company.com"],
            "Groups": [
              { "Name": "beta", "RolloutPercentage": 100 },
              { "Name": "all",  "RolloutPercentage": 5 }
            ],
            "DefaultRolloutPercentage": 0
          }
        }
      }]
    },

    "HolidayPromo": {
      "EnabledFor": [{
        "Name": "TimeWindow",
        "Parameters": {
          "Start": "2026-12-20T00:00:00Z",
          "End":   "2026-12-31T23:59:59Z"
        }
      }]
    }
  }
}

Utilisation dans le code

// Via attribut (gate au niveau contrôleur/action)
[FeatureGate("NewDashboard")]
[ApiController]
public class DashboardController : ControllerBase { }

// Via injection
public class PaymentService(IFeatureManager fm)
{
    public async Task<PaymentResult> Process(PaymentRequest req)
    {
        if (await fm.IsEnabledAsync("NewPaymentEngine"))
            return await ProcessV2(req);

        return await ProcessV1(req); // fallback explicite, toujours présent
    }
}

// Dans les vues Razor
@inject IFeatureManager FeatureManager
@if (await FeatureManager.IsEnabledAsync("NewCheckout"))
{
    <CheckoutV2 />
}

OpenFeature (.NET — standard multi-provider)

dotnet add package OpenFeature
dotnet add package LaunchDarkly.OpenFeature.ServerProvider
// Program.cs
var ldConfig = Configuration.Builder("sdk-key-xxx").Build();
await Api.Instance.SetProviderAsync(new Provider(ldConfig));
builder.Services.AddSingleton(Api.Instance.GetClient());

Évaluation typique avec contexte

public class FeatureFlagService(FeatureClient client)
{
    public async Task<bool> IsNewEngineEnabledAsync(string userId, string country)
    {
        var ctx = EvaluationContext.Builder()
            .Set("userId", userId)
            .Set("country", country)
            .Build();

        // Toujours fournir une valeur par défaut sûre en 2e argument
        return await client.GetBooleanValueAsync("new-payment-engine", false, ctx);
    }

    public async Task<double> GetFeePercentageAsync()
    {
        // Flag numérique avec fallback
        return await client.GetDoubleValueAsync("fee-percentage", 2.5);
    }
}

Avantage OpenFeature : changer de provider (LaunchDarkly → Unleash → custom) sans toucher au code métier.


Stratégie de rollout progressif

Jour 1  : 0% → internes seulement (liste blanche)
Jour 3  : 1%  → surveiller erreurs / latences
Jour 5  : 10% → confirmer métriques OK
Jour 8  : 30%
Jour 10 : 100% → planifier nettoyage du flag

Critères de go/no-go avant chaque palier :


Cycle de vie & gouvernance

PhaseActionResponsable
CréationNommer le flag, documenter la finalité, fixer date d'expirationDev
DevImplémenter les deux branches, écrire les testsDev
StagingActiver à 100% en staging, validerQA
Prod rolloutIncrémenter par paliersProduct + Dev
NettoyageSupprimer le flag ET le code conditionnel de l'ancienne brancheDev
# Exemple : recherche des flags à nettoyer dans le codebase
grep -r "IsEnabledAsync\|FeatureGate\|GetBooleanValue" src/ \
  | grep -v "\.md:" | grep -v "_test" \
  | sort | uniq

Monitoring & observabilité

// Middleware de logging des évaluations
public class FlagAuditMiddleware(RequestDelegate next, ILogger<FlagAuditMiddleware> logger)
{
    public async Task InvokeAsync(HttpContext ctx, IFeatureManager fm)
    {
        var flags = new[] { "NewDashboard", "NewPaymentEngine" };
        foreach (var flag in flags)
        {
            var enabled = await fm.IsEnabledAsync(flag);
            logger.LogInformation("FeatureFlag:{Flag} Enabled:{Enabled} User:{User}",
                flag, enabled, ctx.User.Identity?.Name);
        }
        await next(ctx);
    }
}

Métriques à exposer (Prometheus/OTLP) :


Garde-fous & anti-patterns

Anti-patternRisqueCorrection
Imbriquer 3+ flagsLogique impossible à testerMax 2 flags imbriqués ; refactorer sinon
Pas de valeur par défautException ou comportement indéterminé si provider downToujours passer le fallback en 2e argument
Flag permanent sans ownerDette technique, "flag zombie"Ajouter expires: et owner dans le nom ou le tag
Même flag pour A/B et kill switchConfusion opérationnelleUn flag = un seul rôle
Évaluer le flag dans une boucle serréeLatence si évaluation réseauÉvaluer une seule fois en début de requête, passer le résultat en paramètre
Supprimer le flag sans supprimer le code mortCode mort, branches unreachablePR de nettoyage obligatoire avant fermeture du ticket

Conventions de nommage

<domaine>-<feature>-<type>
payment-new-engine-release       # release toggle
checkout-promo-experiment        # A/B test
api-rate-limit-ops               # kill switch
dashboard-v2-rollout             # rollout progressif

Préfixe par domaine → facilite le filtrage dans les dashboards et les recherches grep.