What Are Feature Flags and Why You Need Them
\nImagine: you've written a cool new feature — for example, smart search with autocomplete. Everything is tested, the code has passed review. But you're not 100% sure users will accept it. Or you're afraid it will fail under load. What to do?
\nIn the past, the answer was simple: "Deploy to production and pray." Today we are smarter. We use feature flags (feature toggles) — a mechanism that allows you to enable and disable functionality on the fly, without recompilation or redeployment.
\nIn this article on PythonLib, we'll explore how to implement feature flags in C# projects — from the simplest implementation to advanced scenarios with A/B testing and canary releases.
\n\nWhy Feature Flags Are a Must-Have for C# Developers
\nFeature flags C# solve three key tasks:
\n- \n
- Safe deployment: Deploy code to production even if the feature isn't ready yet. Just disable the flag. \n
- Instant disabling: Something went wrong? One click in the admin panel — and the problematic feature disappears. \n
- Flexible feature management: Enable features for specific users, regions, or by time. \n
And the best part: for feature management in .NET, you don't need to reinvent the wheel — there's a ready-made library Microsoft.FeatureManagement.
The Simplest Way: Configuration File
\nLet's start with a basic approach — via appsettings.json. This is ideal for simple feature toggles .NET.
Step 1. Add Settings
\n{\n "FeatureManagement": {\n "NewSearchEngine": true,\n "DarkMode": false,\n "BetaDashboard": true\n }\n}\n\nStep 2. Register the Service
\nIn Program.cs, add:
builder.Services.AddFeatureManagement();\n\nStep 3. Use in Code
\npublic class SearchController\n{\n private readonly IFeatureManager _featureManager;\n\n public SearchController(IFeatureManager featureManager)\n {\n _featureManager = featureManager;\n }\n\n public async Task<IActionResult> Search(string query)\n {\n if (await _featureManager.IsEnabledAsync("NewSearchEngine"))\n {\n return View("NewSearch", await _newEngine.SearchAsync(query));\n }\n return View("LegacySearch", await _oldEngine.SearchAsync(query));\n }\n}\nDone! Now, to enable a new feature, just change true to false in the config and restart the application. But we want to do it without a restart, right?
Dynamic Feature Flags: Switching Without Restart
\nFor conditional features C# without reloading, use configuration providers that load changes. The best option is a database or Redis.
\n\nCreate a Provider from a Database
\npublic class DatabaseFeatureDefinitionProvider : IFeatureDefinitionProvider\n{\n private readonly AppDbContext _db;\n\n public DatabaseFeatureDefinitionProvider(AppDbContext db)\n {\n _db = db;\n }\n\n public async Task<FeatureDefinition> GetFeatureDefinitionAsync(string featureName)\n {\n var feature = await _db.FeatureFlags\n .FirstOrDefaultAsync(f => f.Name == featureName);\n \n return feature != null \n ? new FeatureDefinition { Name = feature.Name, EnabledFor = feature.EnabledFor }\n : null;\n }\n\n public IAsyncEnumerable<FeatureDefinition> GetAllFeatureDefinitionsAsync()\n {\n return _db.FeatureFlags\n .Select(f => new FeatureDefinition { Name = f.Name, EnabledFor = f.EnabledFor })\n .AsAsyncEnumerable();\n }\n}\n\nRegister it:
\nbuilder.Services.AddFeatureManagement