A concurrency limit or an expensive fallback path may need to change before you can rebuild and deploy the application. Put controls like these in Azure App Configuration:
builder.Configuration.AddAzureAppConfiguration(options =>
{
options.Connect(
new Uri(builder.Configuration["AppConfigurationEndpoint"]!),
new DefaultAzureCredential())
.Select("SupportApi:*")
.ConfigureRefresh(refresh =>
refresh.RegisterAll()
.SetRefreshInterval(TimeSpan.FromSeconds(30)));
});
builder.Services.AddAzureAppConfiguration();
builder.Services.Configure<AiRuntimeOptions>(
builder.Configuration.GetSection("SupportApi:Ai"));
WebApplication app = builder.Build();
app.UseAzureAppConfiguration();
Application code can read refreshed values through IOptionsSnapshot<T>. It is scoped and creates a snapshot when first accessed in a request, so it cannot be injected directly into a singleton service:
public sealed class ReplyService(
IOptionsSnapshot<AiRuntimeOptions> options)
{
public bool IsEnabled => options.Value.Enabled;
}
Use IOptionsMonitor<T> in singleton or longer-lived services that need the current value or change notifications.
Dynamic configuration does not mean instant global consistency. The ASP.NET Core middleware checks for changes when a request arrives and the refresh interval has elapsed. The refresh runs asynchronously, so the request that triggers it may still read the previous value. An idle instance will not refresh until it receives another request. Instances can temporarily observe different versions, so each switch must be safe during that window.
The 30-second interval in the example is not a recommendation. Choose it based on how long a stale value is acceptable.
RegisterAll() watches every selected key. When several values form one logical change, consider watching a sentinel key instead. Update the related values first and the sentinel last to avoid refreshing while the logical change is still being written.
An ordinary Boolean value can work as a kill switch. It is still normal configuration. If you need feature targeting, schedules, or variants, load feature flags with UseFeatureFlags(...) and register feature-management services with AddFeatureManagement(). Do not hide a complex deployment migration behind either kind of switch.
App Configuration is not a general secret store. Prefer managed identity when you can eliminate credentials. Use Key Vault for secrets that must still exist.
Before adding a switch, decide who owns it and what the safe default should be. Record why it exists and when it can be removed. Telemetry should show which state is active.
Use runtime configuration for reversible operational decisions. Do not use operational switches to bypass authorization or application invariants. Keep schema changes in deployment workflows.