PrimusSaaS.FeatureFlags
1.0.0
See the version list below for details.
dotnet add package PrimusSaaS.FeatureFlags --version 1.0.0
NuGet\Install-Package PrimusSaaS.FeatureFlags -Version 1.0.0
<PackageReference Include="PrimusSaaS.FeatureFlags" Version="1.0.0" />
<PackageVersion Include="PrimusSaaS.FeatureFlags" Version="1.0.0" />
<PackageReference Include="PrimusSaaS.FeatureFlags" />
paket add PrimusSaaS.FeatureFlags --version 1.0.0
#r "nuget: PrimusSaaS.FeatureFlags, 1.0.0"
#:package PrimusSaaS.FeatureFlags@1.0.0
#addin nuget:?package=PrimusSaaS.FeatureFlags&version=1.0.0
#tool nuget:?package=PrimusSaaS.FeatureFlags&version=1.0.0
PrimusSaaS Feature Flags
Lightweight feature flag management for .NET applications. Supports in-memory, file-based, and Azure App Configuration providers.
Features
- Multiple Providers: In-memory, JSON file, or Azure App Configuration
- Percentage Rollouts: Gradual feature rollouts with consistent hashing
- User Targeting: Enable features for specific users or groups
- Time-Based Activation: Schedule feature availability windows
- Hot Reload: JSON file provider supports live updates
- ASP.NET Core Integration: DI extensions and middleware support
Installation
dotnet add package PrimusSaaS.FeatureFlags
Quick Start
1. Register Services
// In Program.cs
builder.Services.AddPrimusFeatureFlags(options =>
{
options.Provider = FeatureFlagProvider.InMemory;
options.Flags["NewDashboard"] = new FeatureFlagDefinition
{
Enabled = true,
Description = "Enable the new dashboard UI"
};
options.Flags["BetaFeature"] = new FeatureFlagDefinition
{
Enabled = false,
RolloutPercentage = 25, // 25% of users
EnabledForGroups = ["beta-testers"]
};
});
2. Use in Controllers/Services
public class DashboardController : ControllerBase
{
private readonly IFeatureFlagService _featureFlags;
public DashboardController(IFeatureFlagService featureFlags)
{
_featureFlags = featureFlags;
}
[HttpGet]
public IActionResult GetDashboard()
{
if (_featureFlags.IsEnabled("NewDashboard", User))
{
return Ok(new { version = "v2", features = GetNewFeatures() });
}
return Ok(new { version = "v1", features = GetLegacyFeatures() });
}
}
Configuration Options
In-Memory Provider (Default)
builder.Services.AddPrimusFeatureFlags(options =>
{
options.Provider = FeatureFlagProvider.InMemory;
options.DefaultValue = false;
options.Flags["MyFeature"] = new FeatureFlagDefinition
{
Enabled = true,
Description = "My awesome feature",
RolloutPercentage = 50,
EnabledForUsers = ["user1@example.com", "user2@example.com"],
EnabledForGroups = ["admins", "beta-testers"],
StartTime = DateTimeOffset.UtcNow,
EndTime = DateTimeOffset.UtcNow.AddDays(30)
};
});
JSON File Provider
builder.Services.AddPrimusFeatureFlags(options =>
{
options.Provider = FeatureFlagProvider.JsonFile;
options.JsonFilePath = "featureflags.json";
});
featureflags.json:
{
"NewDashboard": {
"Enabled": true,
"Description": "New dashboard UI",
"RolloutPercentage": 100
},
"BetaFeature": {
"Enabled": false,
"RolloutPercentage": 25,
"EnabledForGroups": ["beta-testers"]
}
}
Configuration Binding
builder.Services.AddPrimusFeatureFlags(options =>
{
builder.Configuration.GetSection("PrimusFeatureFlags").Bind(options);
});
appsettings.json:
{
"PrimusFeatureFlags": {
"Provider": "InMemory",
"DefaultValue": false,
"CacheDurationSeconds": 30,
"Flags": {
"NewDashboard": {
"Enabled": true,
"RolloutPercentage": 50
}
},
"Logging": {
"LogEvaluations": true,
"IncludeUserContext": false
}
}
}
Feature Flag Evaluation
Simple Check
if (_featureFlags.IsEnabled("MyFeature"))
{
// Feature is enabled globally
}
User-Specific Check
// With user ID
if (_featureFlags.IsEnabled("MyFeature", "user123"))
{
// Feature is enabled for this user
}
// With ClaimsPrincipal (from HttpContext.User)
if (_featureFlags.IsEnabled("MyFeature", User))
{
// Feature is enabled based on user claims
}
Custom Context
var context = new FeatureFlagContext
{
UserId = "user123",
Email = "user@example.com",
Groups = ["admins", "beta-testers"],
Attributes = { ["region"] = "us-west" }
};
if (_featureFlags.IsEnabled("MyFeature", context))
{
// Feature is enabled for this context
}
Async Evaluation
var isEnabled = await _featureFlags.IsEnabledAsync("MyFeature", User);
Targeting Rules
Feature flags are evaluated in the following order:
- Time-Based: Check if current time is within StartTime/EndTime window
- User Targeting: Check if user ID is in EnabledForUsers list
- Group Targeting: Check if user belongs to any EnabledForGroups
- Percentage Rollout: Use consistent hashing to determine if user is in rollout
- Global Enabled: Fall back to the Enabled flag
API Reference
IFeatureFlagService
| Method | Description |
|---|---|
IsEnabled(featureName) |
Check if feature is globally enabled |
IsEnabled(featureName, userId) |
Check if feature is enabled for user ID |
IsEnabled(featureName, ClaimsPrincipal) |
Check if feature is enabled for claims |
IsEnabled(featureName, context) |
Check with custom context |
GetAllFlagsAsync() |
Get all feature flags and states |
GetFlagDefinitionAsync(featureName) |
Get feature flag definition |
RefreshAsync() |
Force refresh from provider |
FeatureFlagDefinition
| Property | Type | Description |
|---|---|---|
Enabled |
bool | Global enabled state |
Description |
string? | Human-readable description |
RolloutPercentage |
int? | Percentage of users (0-100) |
EnabledForUsers |
List<string> | User IDs always enabled |
EnabledForGroups |
List<string> | Group names always enabled |
StartTime |
DateTimeOffset? | Activation start (UTC) |
EndTime |
DateTimeOffset? | Activation end (UTC) |
Metadata |
Dictionary<string, string> | Custom key-value pairs |
Best Practices
- Use meaningful flag names:
NewCheckoutFlownotfeature1 - Set descriptions: Document what each flag controls
- Clean up old flags: Remove flags after full rollout
- Use percentage rollouts: Gradual rollouts reduce risk
- Monitor evaluations: Enable logging to track usage
Related Packages
PrimusSaaS.Identity.Validator- Multi-issuer JWT validationPrimusSaaS.Logging- Structured logging with PII maskingPrimusSaaS.Notifications- Email/SMS notifications
License
MIT License - see LICENSE for details.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net6.0 is compatible. net6.0-android was computed. net6.0-ios was computed. net6.0-maccatalyst was computed. net6.0-macos was computed. net6.0-tvos was computed. net6.0-windows was computed. net7.0 is compatible. net7.0-android was computed. net7.0-ios was computed. net7.0-maccatalyst was computed. net7.0-macos was computed. net7.0-tvos was computed. net7.0-windows was computed. net8.0 is compatible. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 was computed. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 was computed. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net6.0
- Microsoft.Extensions.Configuration.Json (>= 7.0.0)
- Microsoft.Extensions.DependencyInjection.Abstractions (>= 7.0.0)
- Microsoft.Extensions.FileProviders.Physical (>= 7.0.0)
- Microsoft.Extensions.Logging.Abstractions (>= 7.0.0)
- Microsoft.Extensions.Options (>= 7.0.0)
- Microsoft.Extensions.Options.ConfigurationExtensions (>= 7.0.0)
- System.Text.Json (>= 8.0.5)
-
net7.0
- Microsoft.Extensions.Configuration.Json (>= 7.0.0)
- Microsoft.Extensions.DependencyInjection.Abstractions (>= 7.0.0)
- Microsoft.Extensions.FileProviders.Physical (>= 7.0.0)
- Microsoft.Extensions.Logging.Abstractions (>= 7.0.0)
- Microsoft.Extensions.Options (>= 7.0.0)
- Microsoft.Extensions.Options.ConfigurationExtensions (>= 7.0.0)
- System.Text.Json (>= 8.0.5)
-
net8.0
- Microsoft.Extensions.Configuration.Json (>= 7.0.0)
- Microsoft.Extensions.DependencyInjection.Abstractions (>= 7.0.0)
- Microsoft.Extensions.FileProviders.Physical (>= 7.0.0)
- Microsoft.Extensions.Logging.Abstractions (>= 7.0.0)
- Microsoft.Extensions.Options (>= 7.0.0)
- Microsoft.Extensions.Options.ConfigurationExtensions (>= 7.0.0)
- System.Text.Json (>= 8.0.5)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
v1.0.0:
- Initial release with in-memory and file-based feature flag providers.
- Percentage rollout support with consistent hashing.
- User targeting by claims (userId, email, groups).
- Time-based activation windows.
- ASP.NET Core DI integration via AddPrimusFeatureFlags().
- Real-time flag evaluation with IFeatureFlagService.