Loading feature flags from new endpoint - #738
Conversation
There was a problem hiding this comment.
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. |
| // The new endpoint uses null to mean "any name". A bare "*" is equivalent. | ||
| if (string.IsNullOrEmpty(nameFilter) || nameFilter == "*") | ||
| { | ||
| nameFilter = null; | ||
| } |
| 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; |
| /// <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; |
|
This needs to go into the preview branch. |
708b5b1 to
56f906e
Compare
| /// 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. |
There was a problem hiding this comment.
| /// 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. | |
| /// When set to true, only enhanced feature flags will be loaded. | |
| /// Defaults to false; All feature flag types are loaded. |
There was a problem hiding this comment.
After further thought, it may be better to skip this API for now, and we can re-introduce it post-preview. When trying out enhanced feature flags, it is most likely to not have any of the concerns that this API aims to resolve, such as spending requests to query empty sets of classic feature flags.
… for old feature flags
…otnetProvider into linglingye/exclude-classic-ff
|
|
||
| public AzureAppConfigurationFeatureFlagClientFactory( | ||
| IEnumerable<string> connectionStrings, | ||
| FeatureFlagClientOptions clientOptions) |
There was a problem hiding this comment.
I am curious about why does FeatureFlagClientOptions support all api version we have.
Should we prevent user from modifying api version for feature flag client?
There was a problem hiding this comment.
The feature flag client is just the configuration client with the 'configuration' methods removed. We can remove the values. One thing to keep in mind is that our clients are just clients sending pipeline requests. Technically a FeatureFlagClient has the ability to send a json payload to app config asking for whatever, and it uses the authentication setup in the client. So, using a pipeline request the customer could use an old api version to access configurations from the feature flag client.
I don't know why anyone would do this, but they could.
There was a problem hiding this comment.
To me, the new feature flag change is not something opt-in. If a customer configured a specific api-version, and he upgraded to the latest provider version. That customer has no knowledge about the new feature flag change (e.g. new api version, new endpoint, etc)
Suddenly, the provider will fail at every request sent by provider to get enhanced feature flag.
This case doesn't apply to .NET provider, because we don't have any public api to set client factory for FaetureFlagClient. But in JS provider, feature flag client options is configurable.
There was a problem hiding this comment.
In .NET provider, there are actually two ways to configure SDK client:
AzureAppConfigurationOptions.ConfigureClientOptions
This method will modify the `ConfigurationClientOptions` and then we will sync retry and audience configuration to `FeatureFlagClientOptions` only (api version is not included)
AzureAppConfigurationOptions.SetClientFactorymethod which allows user to set aIAzureClientFactory<ConfigurationClient>. It only works forConfigurationClient
We will not sync the configuration change made by the custom ConfigurationClient factory to FeatureFlagClient. (I am not sure whether this implementation is intended)
In theory, both ways could touch api version for ConfigurationClient. But in our current implementation for .NET provider, the wrong api version issue for feature flag client will never happen. (This is different from JS provider's current implementation)
There was a problem hiding this comment.
To me, the new feature flag change is not something opt-in. If a customer configured a specific api-version, and he upgraded to the latest provider version. That customer has no knowledge about the new feature flag change (e.g. new api version, new endpoint, etc) Suddenly, the provider will fail at every request sent by provider to get enhanced feature flag.
This case doesn't apply to .NET provider, because we don't have any public api to set client factory for
FaetureFlagClient. But in JS provider, feature flag client options is configurable.
We can have doc/release note to cover the api version change and enhanced feature flag only available in 2026-05-01-Preview.
Since all the SDK/Providers will support enhanced feature flags in preview version, if users do not want to use this feature, they can remain on the existing stable version.
For JS users, if they declare a dependency like "@azure/app-configuration-provider": "^2.5.0", it will not automatically upgrade to a preview version. For users who explicitly set the API version, there is no risk of their applications being broken by an automatic upgrade. In other words, adopting Enhanced Feature Flags requires an intentional move to a preview version rather than happening implicitly through dependency updates.
Adds support for loading feature flags from Azure App Configuration's new feature-flag endpoint , rather than only reading "classic" flags stored as key-values prefixed with
.appconfig.featureflag/.Changes:
FeatureFlagSelector, fetches flags via the dedicated SDK endpoint, with change detection/refresh support.V2026_05_01_Preview.ToConfiguration(...)to convert aFeatureFlaginto configuration key-values. Removed adapter pattern for feature flags.0..N-1; new standalone flags continue from the classic flag count (feature_management:feature_flags:{index}).