Using Microsoft.FeatureManagement Without Azure App Configuration

Search for Microsoft.FeatureManagement and most tutorials end up at Azure App Configuration. It's a good service, but the library doesn't care where flags come from. It reads them through an interface, and you decide what's behind it.

Option 1: appsettings.json (or any configuration source)

AddFeatureManagement() reads flags from IConfiguration: appsettings.json, environment variables, user secrets, or any other provider.

builder.Services.AddFeatureManagement();

{
  "FeatureManagement": {
    "NewDashboard": true
  }
}

You get no new dependencies and flags in source control. The cost: changing a flag means changing a file or variable on every server, which usually means a deployment. There's no dashboard and no audit trail beyond git. For a handful of flags that change with deployments, this is the right answer.

Option 2: A custom IFeatureDefinitionProvider

The library asks an IFeatureDefinitionProvider for definitions. Replace the default with your own, backed by a database or an API:

public class DatabaseFeatureDefinitionProvider(IFlagStore store) : IFeatureDefinitionProvider
{
    public async IAsyncEnumerable<FeatureDefinition> GetAllFeatureDefinitionsAsync()
    {
        foreach (var flag in await store.GetAllAsync())
            yield return ToDefinition(flag);
    }

    public async Task<FeatureDefinition> GetFeatureDefinitionAsync(string featureName)
    {
        var flag = await store.GetAsync(featureName);
        return flag is null ? new FeatureDefinition { Name = featureName } : ToDefinition(flag);
    }

    private static FeatureDefinition ToDefinition(Flag flag) => new()
    {
        Name = flag.Name,
        EnabledFor = flag.Enabled ? [new FeatureFilterConfiguration { Name = "AlwaysOn" }] : []
    };
}

Register it after AddFeatureManagement() and it replaces the default:

builder.Services.AddFeatureManagement();
builder.Services.AddSingleton<IFeatureDefinitionProvider, DatabaseFeatureDefinitionProvider>();

You get full control. The cost: flag checks call your provider, so you'll want a cache, and then you own invalidation, the management UI, the audit trail, and access control.

Option 3: A hosted service

A hosted service is option 2 with someone else building the provider, the dashboard, and the cache. The FeatureFlags.app client registers an IFeatureDefinitionProvider, refreshes your flags in the background, and keeps an in-memory copy so checks never wait on the network.

using Acmi.FeatureFlags.Client;

builder.AddFeatureFlags();

Your IFeatureManager, [FeatureGate], and <feature> code doesn't change. You get a dashboard, audit logs, environments, and changes without a deployment. The cost: another service, with a price that grows with flag count. Changes arrive on the refresh interval (15 minutes by default), not instantly. If your app starts while the service is unreachable, flags are off until the first fetch.

Where Azure App Configuration fits

It's option 3 with Azure behind it. If you already run on Azure with managed identities, it's a great fit: settings, Key Vault references, and flags in one place. The trade is an Azure subscription and managing flags in the portal.

The code that checks your flags is the same in every option, so you can move between them.

The best feature flag system is the one your team will actually keep clean.