IFeatureFlagService Interface Reference¶
Overview¶
IFeatureFlagService is the primary service interface for managing feature flags in Flaggy. It provides a comprehensive set of methods for checking flag status, retrieving values, and performing CRUD operations. This service automatically handles cache invalidation for all modifications.
Namespace: Flaggy.Abstractions
Core Methods¶
IsEnabledAsync¶
Checks whether a feature flag is enabled.
Task<bool> IsEnabledAsync(string key, CancellationToken cancellationToken = default);
Parameters:
- key (string): The unique identifier for the feature flag
- cancellationToken (CancellationToken, optional): Token to cancel the async operation
Returns: Task<bool> - True if the flag exists and is enabled, false otherwise
Example:
var flagService = serviceProvider.GetRequiredService<IFeatureFlagService>();
if (await flagService.IsEnabledAsync("new-checkout-flow"))
{
// Use new checkout flow
return GetNewCheckoutFlow();
}
else
{
// Use legacy checkout flow
return GetLegacyCheckoutFlow();
}
Use Cases: - Feature toggling in controllers or services - A/B testing implementations - Progressive rollout of new features
GetValueAsync (String)¶
Retrieves the string value of a feature flag with an optional default value.
Task<string?> GetValueAsync(string key, string? defaultValue = null, CancellationToken cancellationToken = default);
Parameters:
- key (string): The unique identifier for the feature flag
- defaultValue (string, optional): Value returned if flag is not found
- cancellationToken (CancellationToken, optional): Token to cancel the async operation
Returns: Task<string?> - The flag's value, default value, or null
Example:
// Get payment gateway with default
var paymentGateway = await flagService.GetValueAsync("payment-gateway", "default-gateway");
// Route to appropriate payment provider
if (paymentGateway == "stripe")
{
return ProcessStripePayment();
}
else if (paymentGateway == "paypal")
{
return ProcessPayPalPayment();
}
else
{
return ProcessDefaultPayment();
}
Use Cases: - Configuration values tied to features - Storing provider selections - Environment-specific feature configuration
GetValueAsync\<T>¶
Retrieves a typed value from a feature flag. Supports value types (structs).
Task<T?> GetValueAsync<T>(string key, T? defaultValue = null, CancellationToken cancellationToken = default) where T : struct;
Type Parameters:
- T: A struct type (int, double, bool, etc.)
Parameters:
- key (string): The unique identifier for the feature flag
- defaultValue (T, optional): Value returned if flag is not found
- cancellationToken (CancellationToken, optional): Token to cancel the async operation
Returns: Task<T?> - The flag's value as type T, default value, or null
Example:
// Get integer value for rate limit
var rateLimit = await flagService.GetValueAsync<int>("api-rate-limit", defaultValue: 100);
ApplyRateLimit(rateLimit.Value);
// Get double value for discount percentage
var discountPercent = await flagService.GetValueAsync<double>("sale-discount", defaultValue: 0.0);
ApplyDiscount(discountPercent.Value);
// Get boolean value
var enableBetaUI = await flagService.GetValueAsync<bool>("beta-ui-enabled", defaultValue: false);
Use Cases: - Numeric thresholds (rate limits, timeouts, quotas) - Percentage values (discounts, probabilities) - Boolean configuration flags
GetFlagAsync¶
Retrieves a complete feature flag object including metadata.
Task<FeatureFlag?> GetFlagAsync(string key, CancellationToken cancellationToken = default);
Parameters:
- key (string): The unique identifier for the feature flag
- cancellationToken (CancellationToken, optional): Token to cancel the async operation
Returns: Task<FeatureFlag?> - The complete FeatureFlag object or null if not found
Example:
var flag = await flagService.GetFlagAsync("new-dashboard");
if (flag != null)
{
Console.WriteLine($"Flag: {flag.Key}");
Console.WriteLine($"Enabled: {flag.IsEnabled}");
Console.WriteLine($"Value: {flag.Value}");
Console.WriteLine($"Description: {flag.Description}");
Console.WriteLine($"Created: {flag.CreatedAt}");
Console.WriteLine($"Updated: {flag.UpdatedAt}");
}
Use Cases: - Admin dashboards displaying flag details - Auditing flag history (CreatedAt, UpdatedAt) - Migrating flag values to other systems
GetAllFlagsAsync¶
Retrieves all feature flags in the system.
Task<IEnumerable<FeatureFlag>> GetAllFlagsAsync(CancellationToken cancellationToken = default);
Parameters:
- cancellationToken (CancellationToken, optional): Token to cancel the async operation
Returns: Task<IEnumerable<FeatureFlag>> - Collection of all FeatureFlag objects
Example:
var allFlags = await flagService.GetAllFlagsAsync();
Console.WriteLine("All Feature Flags:");
foreach (var flag in allFlags)
{
var status = flag.IsEnabled ? "✓" : "✗";
Console.WriteLine($" [{status}] {flag.Key}: {flag.Description}");
}
Use Cases: - Admin panels and dashboards - Initialization and startup verification - Bulk operations on flags
RefreshCacheAsync¶
Forces a refresh of the internal cache by reloading all flags from the provider.
Task RefreshCacheAsync(CancellationToken cancellationToken = default);
Parameters:
- cancellationToken (CancellationToken, optional): Token to cancel the async operation
Example:
// After external flag modification (direct database update)
await flagService.RefreshCacheAsync();
// Now get latest values
var flag = await flagService.GetFlagAsync("feature-key");
Use Cases: - Synchronizing with external updates to flags - Manual cache invalidation after batch operations - Debugging cache consistency issues
CRUD Operations¶
CreateFlagAsync¶
Creates a new feature flag in the system.
Task<bool> CreateFlagAsync(FeatureFlag flag, CancellationToken cancellationToken = default);
Parameters:
- flag (FeatureFlag): The feature flag to create
- cancellationToken (CancellationToken, optional): Token to cancel the async operation
Returns: Task<bool> - True if created successfully, false otherwise
Example:
var newFlag = new FeatureFlag
{
Key = "new-checkout-flow",
IsEnabled = false,
Description = "Enable new checkout flow",
Value = null
};
bool created = await flagService.CreateFlagAsync(newFlag);
if (created)
{
Console.WriteLine("Flag created successfully");
}
else
{
Console.WriteLine("Failed to create flag (may already exist)");
}
Use Cases: - Adding new features to flag management - Initializing flags at application startup - Creating flags programmatically
UpdateFlagAsync¶
Updates an existing feature flag.
Task<bool> UpdateFlagAsync(FeatureFlag flag, CancellationToken cancellationToken = default);
Parameters:
- flag (FeatureFlag): The feature flag with updated values
- cancellationToken (CancellationToken, optional): Token to cancel the async operation
Returns: Task<bool> - True if updated successfully, false if flag not found
Example:
var flag = await flagService.GetFlagAsync("new-checkout-flow");
if (flag != null)
{
flag.IsEnabled = true;
flag.Value = "v2-optimized";
flag.Description = "Enable new checkout flow - optimized version";
bool updated = await flagService.UpdateFlagAsync(flag);
if (updated)
{
Console.WriteLine("Flag updated successfully");
}
}
Use Cases: - Toggling flags on/off - Updating flag configuration values - Changing flag descriptions
DeleteFlagAsync¶
Deletes a feature flag from the system.
Task<bool> DeleteFlagAsync(string key, CancellationToken cancellationToken = default);
Parameters:
- key (string): The unique identifier of the flag to delete
- cancellationToken (CancellationToken, optional): Token to cancel the async operation
Returns: Task<bool> - True if deleted successfully, false if flag not found
Example:
bool deleted = await flagService.DeleteFlagAsync("deprecated-feature");
if (deleted)
{
Console.WriteLine("Flag deleted successfully");
}
else
{
Console.WriteLine("Flag not found");
}
Use Cases: - Removing deprecated features - Cleanup of temporary flags - Archive management
Common Patterns¶
Pattern 1: Feature Toggle¶
public class PricingController
{
private readonly IFeatureFlagService _flagService;
public PricingController(IFeatureFlagService flagService)
{
_flagService = flagService;
}
public async Task<IActionResult> GetPricing()
{
if (await _flagService.IsEnabledAsync("dynamic-pricing"))
{
return Ok(GetDynamicPricing());
}
return Ok(GetStaticPricing());
}
private object GetDynamicPricing() => new { /* dynamic pricing logic */ };
private object GetStaticPricing() => new { /* static pricing logic */ };
}
Pattern 2: Configuration Values¶
public class NotificationService
{
private readonly IFeatureFlagService _flagService;
public NotificationService(IFeatureFlagService flagService)
{
_flagService = flagService;
}
public async Task SendNotificationAsync(string userId, string message)
{
var provider = await _flagService.GetValueAsync("notification-provider", "email");
switch (provider)
{
case "sms":
await SendSmsAsync(userId, message);
break;
case "push":
await SendPushAsync(userId, message);
break;
default:
await SendEmailAsync(userId, message);
break;
}
}
}
Pattern 3: Admin Management¶
[ApiController]
[Route("api/[controller]")]
public class FeatureFlagsController : ControllerBase
{
private readonly IFeatureFlagService _flagService;
public FeatureFlagsController(IFeatureFlagService flagService)
{
_flagService = flagService;
}
[HttpGet]
public async Task<ActionResult<IEnumerable<FeatureFlag>>> GetAll()
{
var flags = await _flagService.GetAllFlagsAsync();
return Ok(flags);
}
[HttpPost]
public async Task<ActionResult<bool>> Create(FeatureFlag flag)
{
var created = await _flagService.CreateFlagAsync(flag);
return created ? Ok(true) : BadRequest("Failed to create flag");
}
[HttpPut("{key}")]
public async Task<ActionResult<bool>> Update(string key, FeatureFlag flag)
{
flag.Key = key;
var updated = await _flagService.UpdateFlagAsync(flag);
return updated ? Ok(true) : NotFound();
}
[HttpDelete("{key}")]
public async Task<ActionResult<bool>> Delete(string key)
{
var deleted = await _flagService.DeleteFlagAsync(key);
return deleted ? Ok(true) : NotFound();
}
}
Related Methods¶
For convenience methods and additional functionality, see: - Extension Methods: FeatureFlagServiceExtensions - Models: FeatureFlag Model - Provider: IFeatureFlagProvider Interface
All modification methods (Create, Update, Delete) automatically trigger cache invalidation to ensure consistency across the application.