Skip to content

Loading feature flags from new endpoint#738

Open
linglingye001 wants to merge 5 commits into
previewfrom
linglingye/exclude-classic-ff
Open

Loading feature flags from new endpoint#738
linglingye001 wants to merge 5 commits into
previewfrom
linglingye/exclude-classic-ff

Conversation

@linglingye001

@linglingye001 linglingye001 commented Jun 12, 2026

Copy link
Copy Markdown
Member

Previously, feature flags were loaded only as classic key-values prefixed with .appconfig.featureflag/. This PR registers a parallel "new feature flag" selector/watcher for each FeatureFlagSelector, fetches flags via the dedicated SDK endpoint, and synthesizes them back into the feature-management JSON schema so downstream parsing is unchanged. Classic flags can be turned off via a new opt-in flag ExcludeClassicFeatureFlags.

Changes:

  • Add opt-in behavior to exclude classic feature flags and prefer the new feature-flag endpoint as the source of truth.
  • Introduce “new feature-flag selector/watcher” markers and update selector equality/hash behavior accordingly.
  • Implement loading + change detection for the new feature-flag endpoint, including synthesis into the existing feature-management JSON schema.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adds support for loading feature flags from Azure App Configuration’s newer feature-flag endpoint and introduces an option to exclude “classic” feature flags stored under the .appconfig.featureflag/ key namespace.

Changes:

  • Add opt-in behavior to exclude classic feature flags and prefer the new feature-flag endpoint as the source of truth.
  • Introduce “new feature-flag selector/watcher” markers and update selector equality/hash behavior accordingly.
  • Implement loading + change detection for the new feature-flag endpoint, including synthesis into the existing feature-management JSON schema.

Reviewed changes

Copilot reviewed 7 out of 7 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
src/Microsoft.Extensions.Configuration.AzureAppConfiguration/Models/KeyValueWatcher.cs Adds a flag to distinguish watchers targeting the new feature-flag endpoint.
src/Microsoft.Extensions.Configuration.AzureAppConfiguration/Models/KeyValueSelector.cs Adds a flag to distinguish selectors for the new endpoint and updates equality/hash logic.
src/Microsoft.Extensions.Configuration.AzureAppConfiguration/FeatureManagement/FeatureFlagSettingConverter.cs New converter that synthesizes ConfigurationSetting instances from SDK FeatureFlag models using the existing feature-management JSON schema.
src/Microsoft.Extensions.Configuration.AzureAppConfiguration/FeatureManagement/FeatureFlagOptions.cs Adds a new public option to exclude classic feature flags.
src/Microsoft.Extensions.Configuration.AzureAppConfiguration/Extensions/ConfigurationClientExtensions.cs Adds change detection for the new feature-flag endpoint by comparing page ETags.
src/Microsoft.Extensions.Configuration.AzureAppConfiguration/AzureAppConfigurationProvider.cs Routes loading/refresh logic between classic key-values and the new feature-flag endpoint; ensures new flags win on key conflicts.
src/Microsoft.Extensions.Configuration.AzureAppConfiguration/AzureAppConfigurationOptions.cs Updates UseFeatureFlags to register new-endpoint selectors/watchers (and optionally omit classic flags); changes default SDK service version.

Comment on lines +350 to +354
// The new endpoint uses null to mean "any name". A bare "*" is equivalent.
if (string.IsNullOrEmpty(nameFilter) || nameFilter == "*")
{
nameFilter = null;
}
Comment on lines 590 to 593
private static ConfigurationClientOptions GetDefaultClientOptions()
{
var clientOptions = new ConfigurationClientOptions(ConfigurationClientOptions.ServiceVersion.V2023_11_01);
var clientOptions = new ConfigurationClientOptions(ConfigurationClientOptions.ServiceVersion.V2026_05_01_Preview);
clientOptions.Retry.MaxRetries = MaxRetries;
Comment on lines +38 to +44
/// <summary>
/// When set to true, classic feature flags (key-values whose key is prefixed with
/// ".appconfig.featureflag/") are not loaded from the configuration store. Only feature flags
/// returned by the new feature-flag endpoint will be loaded.
/// Defaults to false; classic flags are loaded alongside new flags for backward compatibility.
/// </summary>
public bool ExcludeClassicFeatureFlags { get; set; } = false;
@linglingye001 linglingye001 marked this pull request as ready for review June 23, 2026 01:23
@linglingye001 linglingye001 changed the title Exclude classic feature flags Loading feature flags from new endpoint Jun 23, 2026
IsNewFeatureFlagSelector = true
};

_selectors.AppendUnique(newFfSelector);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should separate key value selectors and feature flag selectors.

And I don't believe we need to duplicate the feature flag selectors and watchers.

Whenever we are processing feature flag selectors we know we must

  1. take the name filter, append the classic feature flag prefix, query classic feature flags
  2. Take the name filter, use it to query standalone (new) feature flags.


foreach (SdkFeatureFlag ff in page.Values)
{
ConfigurationSetting synthesized = FeatureFlagSettingConverter.ToConfigurationSetting(ff);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The new feature flags shouldn't be converted to configuration setting. When we load a new feature flag, we should break it down into it's associated key-value pairs, like the feature flag adapter does for classic feature flags, and inject that into the configuration directly.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I saw some updates in the PR. Is this one still being worked on?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, working in progess

@jimmyca15

Copy link
Copy Markdown
Member

This needs to go into the preview branch.

@linglingye001 linglingye001 force-pushed the linglingye/exclude-classic-ff branch from 708b5b1 to 56f906e Compare June 25, 2026 09:50
@zhiyuanliang-ms zhiyuanliang-ms changed the base branch from main to preview June 25, 2026 09:58
{
var selector = new SettingSelector()
{
KeyFilter = FeatureManagementConstants.FeatureFlagMarker + (ffSelector.NameFilter ?? "*"),

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This fall back to "*" is interesting. How would we end up with a feature flag selector with a null name filter. would that be

ffOptions.Select(null);

I would've thought that we would throw if someone passes null for the name filter.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants