← Back to all posts

Azure Feature Flags with App Configuration in .NET

Azure Feature Flags with App Configuration in .NET

Reading Time: 5 minutes

The Problem

Shipping code and exposing behavior are not the same thing.

Without feature flags, every change is tightly coupled to deployment:

  • a new feature goes live the moment the code is deployed
  • risky behavior cannot be enabled gradually
  • rollback means redeploying old code
  • experiments and staged rollouts become awkward
  • teams end up merging late, delaying releases, or hiding unfinished behavior behind branch complexity

That is manageable when the application is small. It becomes painful when multiple teams ship continuously or when business stakeholders want controlled releases.

The real problem is not just deployment speed. It is lack of control over when behavior becomes active.

The Solution

Azure App Configuration includes feature flag support that works naturally with .NET applications.

This lets you separate:

  • deployment: shipping code to production
  • release: enabling the behavior for users

Feature flags help you:

  • enable or disable features without redeploying
  • roll out gradually
  • target behavior by environment or audience
  • keep risky changes behind explicit controls
  • disable a problematic feature quickly without reverting the entire deployment

In practice, feature flags are one of the simplest ways to reduce deployment risk.

What a Feature Flag Actually Is

A feature flag is just a named switch evaluated at runtime.

Instead of hardcoding behavior like this:

if (DateTime.UtcNow >= launchDate)
{
    // new behavior
}

You move the decision into configuration:

if (await featureManager.IsEnabledAsync("Checkout.NewPricing"))
{
    // new behavior
}

Now the release decision is externalized and controlled operationally.

.NET Setup

Install the packages:

dotnet add package Microsoft.Extensions.Configuration.AzureAppConfiguration
dotnet add package Microsoft.FeatureManagement.AspNetCore
dotnet add package Azure.Identity

Add the App Configuration endpoint to configuration:

{
  "AzureAppConfiguration": {
    "Endpoint": "https://your-app-config.azconfig.io"
  }
}

Registering Feature Flags

In Program.cs, connect to Azure App Configuration and enable feature flags.

using Azure.Identity;
using Microsoft.FeatureManagement;

var builder = WebApplication.CreateBuilder(args);

var endpoint = builder.Configuration["AzureAppConfiguration:Endpoint"];

if (!string.IsNullOrWhiteSpace(endpoint))
{
    builder.Configuration.AddAzureAppConfiguration(options =>
    {
        options.Connect(new Uri(endpoint), new DefaultAzureCredential())
            .UseFeatureFlags(featureFlagOptions =>
            {
                featureFlagOptions.CacheExpirationInterval = TimeSpan.FromMinutes(5);
            });
    });

    builder.Services.AddAzureAppConfiguration();
}

builder.Services.AddFeatureManagement();

var app = builder.Build();

app.UseAzureAppConfiguration();

This gives you:

  • access to App Configuration through managed identity or local developer credentials
  • automatic feature flag loading
  • a configurable cache interval for flag refresh

Checking a Feature Flag in Code

The simplest usage is injecting IFeatureManager.

using Microsoft.FeatureManagement;

public sealed class CheckoutService
{
    private readonly IFeatureManager _featureManager;

    public CheckoutService(IFeatureManager featureManager)
    {
        _featureManager = featureManager;
    }

    public async Task<decimal> CalculatePriceAsync(Order order)
    {
        if (await _featureManager.IsEnabledAsync("Checkout.NewPricing"))
        {
            return CalculateNewPrice(order);
        }

        return CalculateLegacyPrice(order);
    }

    private static decimal CalculateNewPrice(Order order) => order.TotalAmount * 0.95m;
    private static decimal CalculateLegacyPrice(Order order) => order.TotalAmount;
}

public sealed class Order
{
    public decimal TotalAmount { get; set; }
}

This is the core value proposition: ship both paths, release one path deliberately.

Using Feature Flags in ASP.NET Core Endpoints

Feature flags also work well at the endpoint level.

app.MapGet("/beta-dashboard", async (IFeatureManager featureManager) =>
{
    if (!await featureManager.IsEnabledAsync("Dashboard.Beta"))
    {
        return Results.NotFound();
    }

    return Results.Ok(new { Message = "Welcome to the beta dashboard" });
});

This is useful when a whole route or feature surface should be unavailable until explicitly enabled.

Strong Operational Use Cases

Feature flags are especially valuable for:

  • new UI flows
  • risky pricing logic
  • migrations between old and new integrations
  • progressive rollout of backend behavior
  • beta-only features
  • kill switches for unstable dependencies or components

A good flag is tied to a release decision. A bad flag is a permanent substitute for design.

Dynamic Refresh

Like normal configuration values, feature flags can be refreshed without restarting the app.

builder.Configuration.AddAzureAppConfiguration(options =>
{
    options.Connect(new Uri(endpoint), new DefaultAzureCredential())
        .UseFeatureFlags(featureFlagOptions =>
        {
            featureFlagOptions.CacheExpirationInterval = TimeSpan.FromSeconds(30);
        });
});

That means an operator can flip a flag in Azure App Configuration and the application will pick it up after the refresh interval.

This is what makes feature flags operationally powerful. The application does not need a new deployment to change behavior.

Security and Access

Feature flags are configuration, so the same security advice applies:

  • use DefaultAzureCredential
  • prefer managed identity in Azure-hosted apps
  • avoid connection strings when identity-based access is available
  • grant only the minimum App Configuration permissions required

A feature flag is not a secret, but it still affects production behavior, so access should be controlled and audited.

Practical Recommendations

A pragmatic feature-flag strategy looks like this:

  • give flags clear names such as Checkout.NewPricing
  • use flags for release control, not as permanent architecture
  • delete stale flags after the rollout is complete
  • keep the old and new code paths understandable while the flag exists
  • use refresh intervals that are sensible for the feature’s operational importance
  • treat flag changes as production-impacting actions with proper ownership

Common Mistakes

Leaving flags forever

If flags never get removed, the codebase becomes harder to understand because every behavior path doubles over time.

Using vague names

A flag called NewFlow becomes meaningless after a few months. A flag called Checkout.NewPricing tells you what is actually being controlled.

Treating flags like authorization

Feature flags control rollout. They are not a substitute for user authorization rules.

Putting too much business logic around one flag

If toggling a single flag changes half the system, the release unit is too large.

Summary

Azure App Configuration feature flags help you release software with much more control than a raw deployment model allows.

For .NET teams, the value is straightforward:

  • deploy code safely
  • turn behavior on deliberately
  • react to problems without redeploying
  • roll out incrementally instead of all at once

The strongest default is:

  • store flags in Azure App Configuration
  • use managed identity and DefaultAzureCredential
  • check flags with IFeatureManager
  • refresh them dynamically
  • remove them once the rollout decision is no longer needed

That gives you safer releases without turning deployments into high-risk events.

References