Skip to content

IFeatureFlagService Extension Methods Reference

Overview

The FeatureFlagServiceExtensions class provides convenient methods built on top of the core IFeatureFlagService interface. These extension methods simplify common operations and reduce boilerplate code.

Namespace: Flaggy.Extensions

Location: /src/Flaggy/Extensions/FeatureFlagServiceExtensions.cs


Flag State Management Extensions

CreateFlagIfNotExistsAsync

Creates a flag only if a flag with the same key doesn't already exist.

public static async Task<bool> CreateFlagIfNotExistsAsync(
    this IFeatureFlagService service,
    string key,
    bool isEnabled = false,
    string? value = null,
    string? description = null,
    CancellationToken cancellationToken = default)

Parameters: - key (string): The unique identifier for the feature flag - isEnabled (bool, optional): Whether the flag starts enabled (default: false) - value (string, optional): Optional value associated with the flag - description (string, optional): Human-readable description - cancellationToken (CancellationToken, optional): Token to cancel the operation

Returns: Task<bool> - True if created, false if already exists

Example:

// Create flag only if it doesn't exist
bool created = await flagService.CreateFlagIfNotExistsAsync(
    key: "dark-mode",
    isEnabled: true,
    description: "Enable dark mode for user interface"
);

if (created)
{
    Console.WriteLine("New flag created");
}
else
{
    Console.WriteLine("Flag already exists");
}

Use Cases: - Idempotent initialization of flags - Safe startup configuration - Preventing duplicate flag creation


UpsertFlagAsync

Creates or updates a flag (insert/update).

public static async Task<bool> UpsertFlagAsync(
    this IFeatureFlagService service,
    string key,
    bool isEnabled,
    string? value = null,
    string? description = null,
    CancellationToken cancellationToken = default)

Parameters: - key (string): The unique identifier for the feature flag - isEnabled (bool): Whether the flag should be enabled - value (string, optional): Optional value associated with the flag - description (string, optional): Human-readable description - cancellationToken (CancellationToken, optional): Token to cancel the operation

Returns: Task<bool> - True if operation succeeded, false otherwise

Example:

// Create or update flag
await flagService.UpsertFlagAsync(
    key: "beta-features",
    isEnabled: false,
    description: "Beta features for testing"
);

// Later, upsert again with updated values
await flagService.UpsertFlagAsync(
    key: "beta-features",
    isEnabled: true,
    value: "phase-2",
    description: "Beta features - Phase 2 enabled"
);

Use Cases: - Configuration synchronization - Safe bulk updates - Merge operations from external sources


Flag Toggle Extensions

EnableFlagAsync

Enables a flag (sets IsEnabled to true).

public static async Task<bool> EnableFlagAsync(
    this IFeatureFlagService service,
    string key,
    CancellationToken cancellationToken = default)

Parameters: - key (string): The unique identifier for the feature flag - cancellationToken (CancellationToken, optional): Token to cancel the operation

Returns: Task<bool> - True if successful, false if flag not found

Example:

// Enable a feature
bool enabled = await flagService.EnableFlagAsync("new-checkout-flow");

if (enabled)
{
    Console.WriteLine("New checkout flow is now enabled");
}
else
{
    Console.WriteLine("Flag not found");
}

Use Cases: - Feature rollout - Activating features - Quick enable operations


DisableFlagAsync

Disables a flag (sets IsEnabled to false).

public static async Task<bool> DisableFlagAsync(
    this IFeatureFlagService service,
    string key,
    CancellationToken cancellationToken = default)

Parameters: - key (string): The unique identifier for the feature flag - cancellationToken (CancellationToken, optional): Token to cancel the operation

Returns: Task<bool> - True if successful, false if flag not found

Example:

// Disable a feature quickly
bool disabled = await flagService.DisableFlagAsync("beta-features");

if (disabled)
{
    Console.WriteLine("Beta features are now disabled");
}

Use Cases: - Emergency feature rollback - Disabling problematic features - Gradual rollout (disable by default)


ToggleFlagAsync

Toggles a flag's enabled state (enabled becomes disabled and vice versa).

public static async Task<bool> ToggleFlagAsync(
    this IFeatureFlagService service,
    string key,
    CancellationToken cancellationToken = default)

Parameters: - key (string): The unique identifier for the feature flag - cancellationToken (CancellationToken, optional): Token to cancel the operation

Returns: Task<bool> - True if successful, false if flag not found

Example:

// Toggle feature on/off
bool toggled = await flagService.ToggleFlagAsync("maintenance-mode");

var flag = await flagService.GetFlagAsync("maintenance-mode");
Console.WriteLine($"Maintenance mode is now: {(flag?.IsEnabled ? "ON" : "OFF")}");

Use Cases: - Quick feature on/off switching - Admin dashboard toggle buttons - Emergency controls


Flag Update Extensions

UpdateFlagValueAsync

Updates only the value of a flag, preserving other properties.

public static async Task<bool> UpdateFlagValueAsync(
    this IFeatureFlagService service,
    string key,
    string? value,
    CancellationToken cancellationToken = default)

Parameters: - key (string): The unique identifier for the feature flag - value (string, optional): The new value - cancellationToken (CancellationToken, optional): Token to cancel the operation

Returns: Task<bool> - True if successful, false if flag not found

Example:

// Update payment gateway configuration
await flagService.UpdateFlagValueAsync("payment-gateway", "stripe-v3");

// Update feature version
await flagService.UpdateFlagValueAsync("checkout-version", "v2-optimized");

// Clear value
await flagService.UpdateFlagValueAsync("feature-config", null);

Use Cases: - Updating configuration values - Changing provider selections - Version upgrades


UpdateFlagDescriptionAsync

Updates only the description of a flag, preserving other properties.

public static async Task<bool> UpdateFlagDescriptionAsync(
    this IFeatureFlagService service,
    string key,
    string? description,
    CancellationToken cancellationToken = default)

Parameters: - key (string): The unique identifier for the feature flag - description (string, optional): The new description - cancellationToken (CancellationToken, optional): Token to cancel the operation

Returns: Task<bool> - True if successful, false if flag not found

Example:

// Update description with rollout progress
await flagService.UpdateFlagDescriptionAsync(
    "dark-mode",
    "Enable dark mode - Rolled out to 25% of users"
);

// Add implementation notes
await flagService.UpdateFlagDescriptionAsync(
    "new-api",
    "New REST API v3 - Replaces GraphQL layer, active in production"
);

Use Cases: - Documentation updates - Rollout progress tracking - Adding implementation notes


Flag Query Extensions

FlagExistsAsync

Checks if a flag exists in the system.

public static async Task<bool> FlagExistsAsync(
    this IFeatureFlagService service,
    string key,
    CancellationToken cancellationToken = default)

Parameters: - key (string): The unique identifier for the feature flag - cancellationToken (CancellationToken, optional): Token to cancel the operation

Returns: Task<bool> - True if flag exists, false otherwise

Example:

// Check before operations
if (await flagService.FlagExistsAsync("deprecated-feature"))
{
    await flagService.DeleteFlagAsync("deprecated-feature");
}

// Validate flag before use
if (!await flagService.FlagExistsAsync("payment-gateway"))
{
    throw new InvalidOperationException("Required flag not found");
}

Use Cases: - Precondition checks - Validation before operations - Safe flag deletion


GetEnabledFlagsAsync

Retrieves all enabled flags.

public static async Task<IEnumerable<FeatureFlag>> GetEnabledFlagsAsync(
    this IFeatureFlagService service,
    CancellationToken cancellationToken = default)

Parameters: - cancellationToken (CancellationToken, optional): Token to cancel the operation

Returns: Task<IEnumerable<FeatureFlag>> - Collection of enabled flags

Example:

// Get all active features
var enabledFlags = await flagService.GetEnabledFlagsAsync();

Console.WriteLine($"Active features ({enabledFlags.Count()}):");
foreach (var flag in enabledFlags)
{
    Console.WriteLine($"  - {flag.Key}: {flag.Description}");
}

Use Cases: - Admin dashboards - Feature activity reports - Enabled feature inventory


GetDisabledFlagsAsync

Retrieves all disabled flags.

public static async Task<IEnumerable<FeatureFlag>> GetDisabledFlagsAsync(
    this IFeatureFlagService service,
    CancellationToken cancellationToken = default)

Parameters: - cancellationToken (CancellationToken, optional): Token to cancel the operation

Returns: Task<IEnumerable<FeatureFlag>> - Collection of disabled flags

Example:

// Get all inactive features
var disabledFlags = await flagService.GetDisabledFlagsAsync();

Console.WriteLine($"Inactive features ({disabledFlags.Count()}):");
foreach (var flag in disabledFlags)
{
    Console.WriteLine($"  - {flag.Key}");
}

// Find flags ready for removal
var oldDisabled = disabledFlags.Where(f =>
    DateTime.UtcNow - f.UpdatedAt > TimeSpan.FromDays(90)
);

Use Cases: - Finding deprecated features - Cleanup operations - Feature inventory management


Bulk Operation Extensions

DeleteFlagsAsync

Deletes multiple flags by their keys.

public static async Task<int> DeleteFlagsAsync(
    this IFeatureFlagService service,
    IEnumerable<string> keys,
    CancellationToken cancellationToken = default)

Parameters: - keys (IEnumerable): Collection of flag keys to delete - cancellationToken (CancellationToken, optional): Token to cancel the operation

Returns: Task<int> - Number of flags successfully deleted

Example:

// Delete multiple flags
var keysToDelete = new[] { "old-feature", "deprecated-api", "temp-flag" };
int deletedCount = await flagService.DeleteFlagsAsync(keysToDelete);

Console.WriteLine($"Deleted {deletedCount} flags");

// Delete flags matching a condition
var disabledOldFlags = (await flagService.GetDisabledFlagsAsync())
    .Where(f => DateTime.UtcNow - f.UpdatedAt > TimeSpan.FromDays(30))
    .Select(f => f.Key);

await flagService.DeleteFlagsAsync(disabledOldFlags);

Use Cases: - Batch deletion - Migration cleanups - Archive management


DeleteAllDisabledFlagsAsync

Deletes all disabled flags in the system.

public static async Task<int> DeleteAllDisabledFlagsAsync(
    this IFeatureFlagService service,
    CancellationToken cancellationToken = default)

Parameters: - cancellationToken (CancellationToken, optional): Token to cancel the operation

Returns: Task<int> - Number of disabled flags deleted

Example:

// Clean up all disabled flags
int deletedCount = await flagService.DeleteAllDisabledFlagsAsync();
Console.WriteLine($"Cleaned up {deletedCount} disabled flags");

Use Cases: - System maintenance - Archive cleanup - Removing deprecated features


Initialization Extensions

SeedFlagsAsync

Creates initial flags only if they don't already exist (idempotent seeding).

public static async Task SeedFlagsAsync(
    this IFeatureFlagService service,
    IEnumerable<FeatureFlag> flags,
    CancellationToken cancellationToken = default)

Parameters: - flags (IEnumerable): Collection of flags to seed - cancellationToken (CancellationToken, optional): Token to cancel the operation

Example:

// Seed default flags at startup
await flagService.SeedFlagsAsync(new[]
{
    new FeatureFlag
    {
        Key = "dark-mode",
        IsEnabled = false,
        Description = "Enable dark mode"
    },
    new FeatureFlag
    {
        Key = "beta-dashboard",
        IsEnabled = false,
        Description = "New dashboard design"
    },
    new FeatureFlag
    {
        Key = "maintenance-mode",
        IsEnabled = false,
        Description = "Enable maintenance mode"
    }
});

Use Cases: - Application startup initialization - Database population scripts - Configuration as code - Idempotent deployments


Reporting Extensions

GetFlagsSummaryAsync

Retrieves summary statistics about all flags.

public static async Task<FlagsSummary> GetFlagsSummaryAsync(
    this IFeatureFlagService service,
    CancellationToken cancellationToken = default)

Returns: Task<FlagsSummary> - Summary object with statistics

FlagsSummary Structure:

public class FlagsSummary
{
    public int TotalCount { get; set; }      // Total number of flags
    public int EnabledCount { get; set; }    // Number of enabled flags
    public int DisabledCount { get; set; }   // Number of disabled flags
}

Example:

// Get summary statistics
var summary = await flagService.GetFlagsSummaryAsync();

Console.WriteLine($"Feature Flags Summary:");
Console.WriteLine($"  Total:    {summary.TotalCount}");
Console.WriteLine($"  Enabled:  {summary.EnabledCount}");
Console.WriteLine($"  Disabled: {summary.DisabledCount}");

// Check enable rate
var enableRate = (double)summary.EnabledCount / summary.TotalCount * 100;
Console.WriteLine($"  Enable Rate: {enableRate:F1}%");

Use Cases: - Admin dashboards - System monitoring - Feature inventory reports - Health checks


Common Usage Patterns

Pattern 1: Feature Initialization

public class Startup
{
    public async Task InitializeAsync(IFeatureFlagService flagService)
    {
        // Create flags only if they don't exist
        await flagService.SeedFlagsAsync(new[]
        {
            new FeatureFlag { Key = "feature-a", IsEnabled = true },
            new FeatureFlag { Key = "feature-b", IsEnabled = false },
        });
    }
}

Pattern 2: Feature Toggling in Controllers

[ApiController]
public class FeatureController : ControllerBase
{
    private readonly IFeatureFlagService _flagService;

    [HttpPost("toggle/{key}")]
    public async Task<IActionResult> Toggle(string key)
    {
        bool toggled = await _flagService.ToggleFlagAsync(key);
        return toggled ? Ok("Toggled") : NotFound();
    }

    [HttpPost("enable/{key}")]
    public async Task<IActionResult> Enable(string key)
    {
        bool enabled = await _flagService.EnableFlagAsync(key);
        return enabled ? Ok("Enabled") : NotFound();
    }
}

Pattern 3: Admin Dashboard

public class DashboardController : ControllerBase
{
    private readonly IFeatureFlagService _flagService;

    [HttpGet("stats")]
    public async Task<IActionResult> GetStats()
    {
        var summary = await _flagService.GetFlagsSummaryAsync();
        var enabled = await _flagService.GetEnabledFlagsAsync();

        return Ok(new {
            summary,
            enabledFeatures = enabled.Select(f => f.Key)
        });
    }
}

Pattern 4: Cleanup Task

public class MaintenanceService
{
    private readonly IFeatureFlagService _flagService;

    public async Task CleanupDeprecatedFlagsAsync()
    {
        var deletedCount = await _flagService.DeleteAllDisabledFlagsAsync();
        Console.WriteLine($"Cleaned up {deletedCount} deprecated flags");
    }
}