Feature Flags in C# with Microsoft Feature Management
Feature flagging is a software development technique that allows
teams to enable or disable application features at runtime without
deploying new code. This article explains the fundamentals of feature
flagging and demonstrates how to implement dynamic feature toggles in C#
using Microsoft's official Microsoft.FeatureManagement
library, covering configuration, dependency injection, endpoint gating,
and dynamic filters.
What Is Feature Flagging?
Feature flagging (also known as feature toggling) separates code deployment from feature release. By wrapping new or experimental code paths in conditional statements evaluated by a flag, developers can continuously integrate and deploy code to production while keeping incomplete features hidden from end users.
Key use cases include:
- Trunk-Based Development: Merging unfinished features into the main branch safely.
- Canary Releases and Gradual Rollouts: Exposing features to a small percentage of users before a full release.
- Kill Switches: Instantly turning off a degraded feature without rolling back the entire application.
- A/B Testing: Providing different experiences to different user segments to measure engagement.
Setting Up Microsoft Feature Management in .NET
Microsoft provides first-class support for feature flags in .NET via
the Microsoft.FeatureManagement.AspNetCore NuGet
package.
1. Install the Package
Run the following command in the .NET CLI:
dotnet add package Microsoft.FeatureManagement.AspNetCore2. Define Flags in Configuration
By default, the library reads from the standard .NET configuration
system under the FeatureManagement section. Add your flags
to appsettings.json:
{
"Logging": {
"LogLevel": {
"Default": "Information"
}
},
"FeatureManagement": {
"BetaDashboard": true,
"NewPaymentGateway": false
}
}Because .NET automatically reloads appsettings.json on
change, updating a boolean value in this file dynamically toggles the
feature in real time without restarting the application.
3. Register the Service
Register the feature management services in
Program.cs:
using Microsoft.FeatureManagement;
var builder = WebApplication.CreateBuilder(args);
// Register Feature Management
builder.Services.AddFeatureManagement();
builder.Services.AddControllers();
var app = builder.Build();
app.UseRouting();
app.MapControllers();
app.Run();Consuming Feature Flags in C
You can evaluate feature flags programmatically or declaratively using routing attributes.
Programmatic Check
Using IFeatureManager
Inject the IFeatureManager interface into your
controllers or services to check feature status asynchronously:
using Microsoft.AspNetCore.Mvc;
using Microsoft.FeatureManagement;
[ApiController]
[Route("api/[controller]")]
public class OrdersController : ControllerBase
{
private readonly IFeatureManager _featureManager;
public OrdersController(IFeatureManager featureManager)
{
_featureManager = featureManager;
}
[HttpPost("checkout")]
public async Task<IActionResult> Checkout()
{
if (await _featureManager.IsEnabledAsync("NewPaymentGateway"))
{
// Code path for the new payment provider
return Ok("Processed via New Payment Gateway");
}
// Fallback to legacy payment provider
return Ok("Processed via Legacy Gateway");
}
}Declarative Checks Using
[FeatureGate]
To restrict entire controllers or specific action methods based on a
flag, use the [FeatureGate] attribute. If the flag is
disabled, the framework automatically returns a
404 Not Found.
using Microsoft.AspNetCore.Mvc;
using Microsoft.FeatureManagement.Mvc;
[ApiController]
[Route("api/[controller]")]
public class BetaController : ControllerBase
{
[FeatureGate("BetaDashboard")]
[HttpGet("dashboard")]
public IActionResult GetDashboard()
{
return Ok(new { Data = "Beta metrics and analytics" });
}
}Implementing Dynamic Feature Filters
Beyond static boolean switches,
Microsoft.FeatureManagement supports dynamic evaluation
using Feature Filters, allowing you to toggle features
based on context, time windows, or percentages.
Built-in Percentage Filter
To roll out a feature gradually to a random percentage of requests, register the built-in filter:
builder.Services.AddFeatureManagement()
.AddFeatureFilter<PercentageFilter>();Then configure the filter in appsettings.json:
{
"FeatureManagement": {
"BetaDashboard": {
"RequirementType": "Any",
"EnabledFor": [
{
"Name": "Percentage",
"Parameters": {
"Value": 25
}
}
]
}
}
}With this configuration,
await _featureManager.IsEnabledAsync("BetaDashboard") will
dynamically evaluate to true roughly 25% of the time.
Centralizing Flags for Distributed Systems
While appsettings.json works for single-instance
applications, microservices and scaled web apps require centralized flag
management. Microsoft.FeatureManagement integrates natively
with Azure App Configuration. By chaining
.AddAzureAppConfiguration() into the .NET configuration
pipeline, flags can be toggled via the Azure portal or CLI and pushed
across all running instances dynamically without service downtime.