Ship code dark with feature flags
Feature flags separate deploying code from releasing it. With Azure App Configuration, you can turn a feature on for 10% of users, or off in an emergency, without a deployment.
Without feature flags, deploying and releasing are the same event. Merging a half-finished feature means hiding it with a long-lived branch, and turning off a misbehaving feature means an emergency deployment.
A feature flag is a switch your code checks at runtime. Deploy the code with the flag off, turn it on when you're ready, and turn it off again in seconds if something goes wrong.
Setting it up
Store flags in Azure App Configuration and read them with the feature management libraries:
builder.Configuration.AddAzureAppConfiguration(options =>
{
options.Connect(new Uri("https://my-config.azconfig.io"), new DefaultAzureCredential())
.UseFeatureFlags(flags => flags.SetRefreshInterval(TimeSpan.FromSeconds(30)));
});
builder.Services.AddAzureAppConfiguration();
builder.Services.AddFeatureManagement();
var app = builder.Build();
app.UseAzureAppConfiguration(); // refreshes flags as requests come in
The packages are Microsoft.Azure.AppConfiguration.AspNetCore and Microsoft.FeatureManagement.AspNetCore.
Checking a flag
app.MapGet("/quotes/{id}", async (Guid id, IFeatureManager features, QuoteService quotes) =>
{
var quote = await features.IsEnabledAsync("NewPricingEngine")
? await quotes.PriceWithNewEngineAsync(id)
: await quotes.PriceAsync(id);
return Results.Ok(quote);
});
For MVC controllers or actions, [FeatureGate("NewPricingEngine")] returns a 404 while the flag is off.
Rolling out gradually
A flag doesn't have to be all or nothing. Built-in filters let you enable it for:
- A percentage of requests, for example 10%, then 50%, then 100%
- Specific users or groups, through the targeting filter, such as internal staff first
- A time window, such as a promotion that switches itself on and off
You change these in the App Configuration portal, and apps pick up the change at their next refresh, within the interval you set.
The kill switch
Flags aren't only for new features. Wrapping a risky integration, such as a call to a new partner API, in a flag gives you an off switch that works faster than any deployment and doesn't need a developer.
Clean up
Every flag is an if statement with two code paths to test and maintain. Once a feature is fully rolled out and stable, remove the flag and the old code path. Keep a short list of active flags with an owner and an expected removal date, or they accumulate for years.
Takeaway
Use feature flags to separate deploying code from releasing it. Store them in Azure App Configuration, roll features out gradually to a percentage or a group of users, keep a kill switch around risky integrations, and remove flags once they've done their job.