Connection strings, feature switches, and service endpoints tend to multiply as an application grows. Keeping each value in deployment settings can work at first, but it gets harder to see which settings belong to which environment and to change them without redeploying. Azure App Configuration gives an ASP.NET Core application a central place to read ordinary settings and feature flags.
The useful part is not simply moving a JSON file into Azure. A good setup also defines how settings are separated by environment, how running instances notice updates, and how sensitive values are handled.
Keep environment differences explicit
Azure App Configuration stores key-value pairs. A key might be MyApp:Orders:PageSize, while its value is 50. Keys can follow the same colon-separated naming convention used by .NET configuration, so application code can read them through IConfiguration just like values from appsettings.json.
Use configuration labels to distinguish values that share a key but belong to different environments. For example, the default label can hold a common value, while labels such as Development and Production hold environment-specific overrides. Load the default values first and the current environment's label afterward so the environment-specific value takes precedence. This keeps environment-specific configuration labels understandable without creating a separate store for every deployment stage.
Do not put secrets in ordinary key-values just because the store is convenient. App Configuration can hold a Key Vault reference instead; the application retrieves the secret from Azure Key Vault when it resolves that reference. The app's identity still needs permission to read the secret.
Connect during application startup
Install the Azure App Configuration provider and Azure Identity packages, then add the provider to the .NET configuration pipeline. The endpoint can be supplied as an environment variable or another local configuration source. In Azure, DefaultAzureCredential can use the application's managed identity; on a developer machine, it can use a supported developer sign-in.
using Azure.Identity;
using Microsoft.Azure.AppConfiguration.AspNetCore;
using Microsoft.Extensions.Configuration.AzureAppConfiguration;
var endpoint = builder.Configuration["AZURE_APPCONFIG_ENDPOINT"]
?? throw new InvalidOperationException("App Configuration endpoint is missing.");
var credential = new DefaultAzureCredential();
builder.Configuration.AddAzureAppConfiguration(options =>
{
options.Connect(new Uri(endpoint), credential)
// Load shared defaults before environment-specific overrides.
.Select("MyApp:*", LabelFilter.Null)
.Select("MyApp:*", builder.Environment.EnvironmentName)
.ConfigureRefresh(refresh =>
{
// Change this key after updating related settings to signal a refresh.
refresh.Register("MyApp:Sentinel", refreshAll: true)
.SetRefreshInterval(TimeSpan.FromSeconds(30));
})
.ConfigureKeyVault(keyVault =>
{
// Use the same identity to resolve Key Vault references.
keyVault.SetCredential(credential);
});
});
builder.Services.AddAzureAppConfiguration();
var app = builder.Build();
// Enables configuration refresh checks as requests pass through the app.
app.UseAzureAppConfiguration();
app.MapGet("/", (IConfiguration config) =>
$"Page size: {config["MyApp:Orders:PageSize"]}");
app.Run();
The selector loads only keys under MyApp:, rather than pulling unrelated values into the application. The sentinel key is a deliberate change signal: after changing a group of related settings, update the sentinel last. That way an instance is less likely to observe a refresh while only part of the change has been published.
Understand what “refresh” means
Adding the provider at startup does not make every running process poll Azure continuously. The UseAzureAppConfiguration middleware checks for refresh as requests pass through the application, subject to the interval you configured. A quiet app may therefore not pick up a change until it receives another request. This dynamic configuration refresh is useful for many web apps, but it is not an instant-push mechanism.
Choose the interval with care. A shorter interval can make changes visible sooner, but it also means more refresh checks. A longer interval reduces checking and accepts a longer wait before instances see an update. Test the behavior with multiple application instances, and make sure the change is safe if different instances briefly run with different values.
Refresh is a good fit for settings that can change while the app is running, such as a display limit or a switch that enables an optional feature. It is not a substitute for restarting when a setting is only read once during startup, nor should it be used to change fundamental process behavior unexpectedly.
Use feature flags for behavior changes
A regular setting can control behavior, but a feature flag makes the intent clearer: this value decides whether a named feature is enabled. Azure App Configuration supports feature flags, and the .NET feature-management library can evaluate them in application code. This is handy for gradually enabling a feature or turning it off while investigating a problem, without treating the flag as a general-purpose configuration value.
Keep flags narrowly named and remove temporary ones when they are no longer needed. A flag that is never retired becomes another permanent branch in the code. Also decide what the application should do if it cannot retrieve updated flag data; critical request paths should have sensible behavior rather than assuming a refresh will always succeed.
Keep local development and access manageable
- Use the same key names locally and in Azure. Local JSON settings can provide developer defaults, while Azure supplies shared or environment-specific values.
- Prefer managed identity in Azure. Grant the app only the required App Configuration data-reading and Key Vault secret-reading permissions.
- Keep the endpoint out of source code. Treat it as environment-specific configuration, even though the endpoint itself is not a secret.
- Check the identity and network path. A correct endpoint is not enough if the app cannot authenticate or reach the stores.
- Test the override order. Confirm that a production label overrides the shared default, and that missing environment-specific keys still fall back as intended.
With those choices made, Azure App Configuration becomes a practical extension of the familiar .NET configuration system, rather than a separate settings framework the application has to work around. Start with a small set of values, verify label precedence and refresh behavior, then add feature flags or Key Vault references only where they solve a real operational need.