9.3 Feature Flags with Azure App Configuration & Feature Manager

Key Takeaways

  • Feature flags (toggles) decouple deployment from release, enabling developers to merge dark code into production continuously while controlling user exposure through configuration.
  • Azure App Configuration provides a centralized, cloud-hosted store for dynamic configuration settings and feature flags, integrating natively with Azure Key Vault for secrets.
  • The Microsoft Feature Management library provides declarative feature evaluation (e.g., [FeatureGate]) supporting advanced filters like PercentageFilter, TargetingFilter, and TimeWindowFilter.
  • Targeting filters enforce consistent, sticky user evaluation across sessions using an ITargetingContextAccessor implementation that extracts user and group claims.
  • Dynamic configuration refresh reloads feature flags at runtime without restarting application processes by monitoring sentinel keys or listening to Azure Event Grid push notifications.
Last updated: September 2026

9.3 Feature Flags with Azure App Configuration & Feature Manager

Continuous Integration requires developers to merge code into the main trunk frequently—often multiple times per day. However, complex business features often take weeks to author. In traditional development, teams isolate uncompleted work on long-lived feature branches, leading to agonizing "merge hell," delayed integration testing, and release friction. Feature Flags (also known as feature toggles or feature gates) resolve this challenge by wrapping uncompleted or high-risk code inside conditional control structures.

On the AZ-400 exam, candidates must understand how to decouple deployment from release using feature flags, manage centralized toggles with Azure App Configuration, configure advanced feature filters (percentage, time window, and targeting), implement zero-restart dynamic configuration refresh, and manage feature flag technical debt.


1. Decoupling Deployment from Release: Dark Launching

Feature flags allow organizations to practice Dark Launching—the practice of deploying compiled code to production while keeping it hidden from end users. The code executes silently in the background, runs against test fixtures, or remains completely dormant until an operator enables the toggle.

[Developer Writes Feature] ──► [Wraps Code in Feature Flag] ──► [Pushes Directly to main]
                                                                         │
                                                                         ▼
[Dark Launch to Prod]    ◄── [Normal CI/CD Runs Daily]      ◄── [Passes Automated PR Tests]
        │
        ▼
[Feature Flag Off: Users see v1] ──► [Operator flips Flag in Cloud] ──► [Feature Flag On: Users see v2]
                                                                         (NO RESTART REQUIRED!)

The Martin Fowler Feature Toggle Taxonomy

Feature flags serve different organizational purposes and have varying lifespans:

  1. Release Toggles: Short-lived (days to weeks) toggles used to allow trunk-based development of incomplete features. Once the feature is released and verified in production, the toggle is permanently retired.
  2. Experiment Toggles (A/B Testing): Short-to-medium-lived toggles used to perform multivariate user experimentation. They route users to variant experiences and collect statistical engagement metrics.
  3. Ops Toggles (Kill Switches): Long-lived toggles designed to protect system stability. If a downstream payment gateway or third-party recommendation engine experiences an outage, operators flip an Ops toggle to disable the non-critical feature gracefully without redeploying code.
  4. Permission Toggles: Long-lived toggles that dynamically control feature availability based on user license tiers (e.g., Free vs. Enterprise tier features).

2. Azure App Configuration Architecture

Traditionally, applications stored feature flags in local configuration files (appsettings.json or web.config) or environment variables. This approach fails in modern distributed cloud architectures: updating a flag requires modifying files across dozens of microservice instances and triggering application restarts.

Azure App Configuration solves this by providing a fully managed, centralized cloud service for configuration and feature flag management.

                                [Azure App Configuration]
                                • Key-Values & Feature Flags
                                • Labeling: Dev, Staging, Prod
                                • Key Vault References: @Microsoft.KeyVault(...)
                                             │
                         ┌───────────────────┼───────────────────┐
                         ▼                   ▼                   ▼
                 [App Service Web]     [AKS Pod Cluster]   [Azure Functions]
                 • Feature Manager     • Feature Manager   • Feature Manager
                 • Dynamic Refresh     • Dynamic Refresh   • Dynamic Refresh

Integration with Azure Key Vault

Azure App Configuration is not designed to store sensitive cryptographic secrets, connection strings with embedded passwords, or private certificates. Instead, it pairs synergistically with Azure Key Vault:

  • Standard configuration settings and feature flags are stored directly in Azure App Configuration.
  • Sensitive credentials are stored in Azure Key Vault.
  • App Configuration stores a Key Vault Reference (a pointer URI such as {"uri":"https://contosokv.vault.azure.net/secrets/DbPassword"}).
  • When the application starts, the Azure App Configuration SDK automatically resolves the pointer, queries Azure Key Vault using Managed Identity (Entra ID), and injects the actual secret into application memory securely.

Feature Flag Schema in App Configuration

In Azure App Configuration, feature flags are stored as specialized key-values:

  • Key Naming Convention: Feature flag keys always carry the prefix .appconfig.featureflag/{FeatureID}.
  • Attributes: Every flag contains an id, description, enabled boolean state, and an optional list of conditions (client filters).
  • Labels: Flags can be segmented using labels (e.g., Development, Staging, Production), allowing a single App Configuration store to serve multiple pipeline environments.

3. Advanced Feature Filters & Targeting Rules

The Microsoft Feature Management framework (Microsoft.FeatureManagement NuGet / npm / pip packages) evaluates whether a feature is active at runtime. While simple flags return a static true or false, complex delivery requires Feature Filters.

1. Percentage Filter (PercentageFilter)

  • Mechanics: Randomly enables a feature for a fixed percentage of total evaluations.
  • Use Case: Testing infrastructure load with synthetic traffic or rolling out low-risk internal optimizations.
  • Limitation: Stateless. A user refreshing the browser may see the feature on request 1, but lose it on request 2.

2. Time Window Filter (TimeWindowFilter)

  • Mechanics: Enables a feature automatically within an explicit UTC start time and end time.
  • Use Case: Activating a Black Friday promotional banner at midnight UTC and disabling it at midnight Monday without requiring an engineer to trigger a pipeline.

3. Targeting Filter (TargetingFilter) — Crucial Exam Concept!

The TargetingFilter provides sophisticated, sticky user rollouts across three distinct evaluation layers:

{
  "id": "NewCheckoutFlow",
  "enabled": true,
  "conditions": {
    "client_filters": [
      {
        "name": "Microsoft.Targeting",
        "parameters": {
          "Audience": {
            "Users": [ "alice@contoso.com", "bob@contoso.com" ],
            "Groups": [
              { "Name": "InternalBetaTesters", "RolloutPercentage": 100 },
              { "Name": "EnterpriseTierCustomers", "RolloutPercentage": 25 }
            ],
            "DefaultRolloutPercentage": 5
          }
        }
      }
    ]
  }
}
  • Targeting Evaluation Hierarchy:
    1. Specific Named Users: If the current user matches an entry in Users, the feature is unconditionally enabled.
    2. User Groups: If the user belongs to a specified group (e.g., EnterpriseTierCustomers), the system calculates a consistent hash of the user ID against the group's RolloutPercentage (e.g., 25%).
    3. Default Rollout Percentage: Any user not matched by named users or groups falls into the global population bucket (e.g., 5%).
  • Session Consistency via ITargetingContextAccessor: To evaluate targeting rules, the application must provide the user's identity and group memberships to the Feature Manager. In ASP.NET Core, developers implement ITargetingContextAccessor:
public class HttpContextTargetingContextAccessor : ITargetingContextAccessor
{
    private readonly IHttpContextAccessor _httpContextAccessor;
    public HttpContextTargetingContextAccessor(IHttpContextAccessor httpContextAccessor) =>
        _httpContextAccessor = httpContextAccessor;

    public ValueTask<TargetingContext> GetContextAsync()
    {
        HttpContext httpContext = _httpContextAccessor.HttpContext;
        var targetingContext = new TargetingContext
        {
            UserId = httpContext.User.Identity?.Name,
            Groups = httpContext.User.Claims
                .Where(c => c.Type == ClaimTypes.Role)
                .Select(c => c.Value)
        };
        return new ValueTask<TargetingContext>(targetingContext);
    }
}

Because the evaluation hashes the UserId, the user is guaranteed to receive the exact same experience across multiple sessions, devices, and browser refreshes.


4. Dynamic Configuration Refresh: Zero-Restart Mechanics

Modifying a feature flag in Azure App Configuration should take effect in running workloads immediately without restarting IIS, recycling Docker containers, or rebooting Kubernetes pods.

The Pull-Based Sentinel Key Pattern

Applications poll Azure App Configuration at a specified interval (CacheExpirationInterval, default 30 seconds). To avoid checking hundreds of individual keys on every poll, best practices mandate the Sentinel Key pattern:

// Program.cs configuration
builder.Configuration.AddAzureAppConfiguration(options =>
{
    options.Connect(builder.Configuration["ConnectionStrings:AppConfig"])
           .Select(KeyFilter.AsValue, LabelFilter.Null)
           .Select(KeyFilter.AsValue, "Production")
           .ConfigureRefresh(refresh =>
           {
               // Register a single sentinel key
               refresh.Register("App:Settings:Sentinel", refreshAll: true)
                      .SetCacheExpiration(TimeSpan.FromSeconds(30));
           })
           .UseFeatureFlags(flagOptions =>
           {
               flagOptions.CacheExpirationInterval = TimeSpan.FromSeconds(30);
           });
});
  • When any configuration setting or feature flag changes, the administrator or pipeline updates the single App:Settings:Sentinel key (e.g., incrementing a version number or timestamp).
  • During the next periodic poll, the application sees that App:Settings:Sentinel changed, and automatically invalidates and reloads its entire configuration cache in a single atomic batch.

The Push-Based Event Grid Pattern

For massive microservice fleets, thousands of pods polling App Configuration every 30 seconds can exceed API request throttling limits and incur cloud billing costs. The enterprise solution is Push-Based Dynamic Refresh:

[Developer Updates Flag] ──► [Azure App Configuration]
                                      │
                                      ▼
                         [Azure Event Grid System Topic]
                         (Microsoft.AppConfiguration.KeyValueModified)
                                      │
                         ┌────────────┴────────────┐
                         ▼                         ▼
              [Webhook: Service A]       [Azure Service Bus Topic]
              (Instant Cache Refresh)              │
                                                   ▼
                                        [AKS Microservice Pods]
                                        (Instant Invalidation)
  1. Azure App Configuration emits an event (KeyValueModified or KeyValueDeleted) to an Azure Event Grid topic whenever a key or flag changes.
  2. Event Grid forwards the event to an application webhook endpoint or an Azure Service Bus topic.
  3. The application receives the push notification and immediately invalidates its internal cache, achieving instantaneous feature toggling with zero polling overhead.

5. Code & Declarative Implementation

In ASP.NET Core, the Feature Management library allows developers to gate entire controllers, individual action methods, or Razor markup declaratively:

// Gating an entire API Controller
[ApiController]
[Route("api/[controller]")]
[FeatureGate("BetaPaymentEngine")]
public class PaymentController : ControllerBase
{
    private readonly IFeatureManager _featureManager;
    public PaymentController(IFeatureManager featureManager) => _featureManager = featureManager;

    [HttpGet("process")]
    public async Task<IActionResult> ProcessPayment()
    {
        // Programmatic toggle evaluation inside code
        if (await _featureManager.IsEnabledAsync("EnhancedFraudCheck"))
        {
            // Execute enhanced ML fraud validation
        }
        return Ok(new { status = "Processed" });
    }
}
<!-- Conditional UI Rendering in Razor Views -->
<feature name="BetaPaymentEngine">
    <button class="btn btn-primary">One-Click Express Checkout</button>
</feature>
<feature name="BetaPaymentEngine" negate="true">
    <button class="btn btn-secondary">Standard Multi-Step Checkout</button>
</feature>

6. Managing Feature Flag Technical Debt & Sunset Governance

While feature flags deliver immense deployment velocity, unmanaged flags represent dangerous technical debt. As flags proliferate:

  • Codebases become cluttered with obsolete if/else conditional logic.
  • The permutation of possible application states explodes exponentially, making comprehensive automated testing impossible.
  • Dead code paths remain in production, increasing cognitive overhead for new developers and risking security regressions if deprecated toggles are accidentally enabled.
   ┌─────────────────────────────────────────────────────────────┐
   │                   Feature Flag Lifecycle                    │
   │                                                             │
   │  [Inception] ──► [Canary Rollout] ──► [100% GA Release]    │
   │                                               │             │
   │                                               ▼             │
   │  [Delete Code & Flag] ◄── [Sprint Story] ◄── [Sunset Phase] │
   └─────────────────────────────────────────────────────────────┘

Enterprise Sunset Governance Rules

  1. Mandatory Expiration Metadata: When a feature flag is created, require tags denoting Owner, CreationDate, and TargetSunsetDate (e.g., maximum 90 days for release toggles).
  2. Pair Flag Creation with Cleanup Work Items: In Azure Boards, whenever a "Feature Toggle" work item is created, immediately create a linked "Technical Debt: Remove Feature Flag" task in the subsequent sprint backlog.
  3. Automated Flag Telemetry & Stale Detection: Use Azure Monitor to audit flag evaluation frequency. If a flag has been enabled at 100% for 30 consecutive days without modification, flag it as "Stale" and alert the engineering lead.
  4. The Sunset Pull Request: The engineering team merges a pull request that deletes the conditional check, deletes the deprecated legacy code path, and deletes the flag from Azure App Configuration.

7. Realistic Exam Scenario & Common Traps

Scenario: Multi-Tenant SaaS Accounting Rollout

Organization: Contoso ERP provides cloud accounting software to 10,000 corporate clients. A newly developed automated tax compliance engine must be deployed to production.

  • Constraint 1: The tax engine must first be activated only for Contoso's internal accounting staff (@contoso.com).
  • Constraint 2: Next, it must be enabled for exactly 20% of users in the Tier1Enterprise customer group.
  • Constraint 3: Users in the 20% cohort must consistently see the new engine on all subsequent logins.
  • Constraint 4: If calculation discrepancies arise, operators must disable the engine in under 10 seconds without restarting any web apps.

DevOps Architect Solution:

  • Centralize configuration in Azure App Configuration with dynamic refresh enabled via a Sentinel Key.
  • Implement the Microsoft.FeatureManagement library in the web application.
  • Configure a TargetingFilter on the TaxComplianceEngine feature flag:
    • Add ContosoInternal to Groups at 100%.
    • Add Tier1Enterprise to Groups at 20%.
    • Implement ITargetingContextAccessor to extract user email and customer tier from the authenticated JWT token.
  • If a calculation defect is reported, operators toggle enabled: false in Azure App Configuration and update the sentinel key. The application refreshes within seconds without container restarts.

Common Exam Traps to Avoid

  • Trap: Selecting PercentageFilter when consistent user experience is required. PercentageFilter evaluates randomly on every request. If an exam question specifies that "users must see the same experience across repeated sessions," the correct answer is TargetingFilter with ITargetingContextAccessor.
  • Trap: Believing feature flag updates require App Service restarts. With the Azure App Configuration provider configured for dynamic refresh (sentinel key or Event Grid), feature flags reload in running memory without restarts.
  • Trap: Storing production passwords or certificates directly in Azure App Configuration. Azure App Configuration is not a secure vault. Always store credentials in Azure Key Vault and reference them via Key Vault References in App Configuration.
Loading diagram...
Azure App Configuration and Dynamic Push/Pull Feature Manager Architecture
Test Your Knowledge

A multi-tenant SaaS company is introducing a redesigned billing dashboard. The engineering team needs to roll out the dashboard exclusively to internal employees first, then to 25% of enterprise tier customers based on company account IDs, and finally to all remaining users over two weeks. A critical requirement is that a user must consistently see the same version of the dashboard across different login sessions and devices. Which Feature Management mechanism must be implemented?

A
B
C
D
Test Your Knowledge

An enterprise microservices application deployed on Azure Kubernetes Service reads hundreds of configuration settings and feature flags from Azure App Configuration. Developers report that updating a feature flag in the Azure Portal does not take effect in the running pods without restarting the deployment. However, configuring each pod to poll Azure App Configuration every 5 seconds exhausts the store's request rate limits and increases cloud billing. What architectural pattern resolves this issue?

A
B
C
D
Test Your Knowledge

An audit of an enterprise codebase reveals over 150 feature flags that were deployed over the past three years. Many toggles point to permanent production features whose legacy code paths are no longer tested or maintained, increasing technical debt and cognitive load on development teams. What operational process should the DevOps architect institute to prevent feature flag accumulation?

A
B
C
D