Skip to content

feat(remote-feature-flag-controller): return threshold values directly and track threshold groups#9289

Open
asalsys wants to merge 4 commits into
mainfrom
feat/remote-feature-flag-threshold-groups
Open

feat(remote-feature-flag-controller): return threshold values directly and track threshold groups#9289
asalsys wants to merge 4 commits into
mainfrom
feat/remote-feature-flag-threshold-groups

Conversation

@asalsys

@asalsys asalsys commented Jun 26, 2026

Copy link
Copy Markdown
Contributor

Summary

  • BREAKING: Threshold feature flags now return the selected value directly from remoteFeatureFlags instead of a { name, value } wrapper object.
  • Add optional featureFlagThresholdGroups state field (Record<string, string>) that maps feature flag names to their selected threshold group name when the selected threshold entry includes thresholdName.
  • Remove normalizeThresholdValue and the legacy { name, value } wrapper fallback for unversioned threshold entries.

Motivation

Separating the processed flag value from threshold group metadata makes it easier for consumers to use threshold flags as plain values (booleans, objects, etc.) without unwrapping. The new featureFlagThresholdGroups field provides explicit access to A/B group assignment when configs opt in via thresholdName.

Migration

Consumers that previously read threshold group names from remoteFeatureFlags[flagName].name should instead:

  1. Read the flag value directly from remoteFeatureFlags[flagName].
  2. Read the threshold group name from featureFlagThresholdGroups[flagName] when available (only populated when the remote config provides thresholdName on the selected threshold entry).

Before:

const flag = remoteFeatureFlags.myThresholdFlag;
// { name: 'groupB', value: { enabled: true } }
const groupName = flag.name;
const value = flag.value;

After:

const value = remoteFeatureFlags.myThresholdFlag;
// { enabled: true }

const groupName = featureFlagThresholdGroups.myThresholdFlag;
// 'groupB' (only when thresholdName is configured)

Test plan

  • yarn workspace @metamask/remote-feature-flag-controller run jest --no-coverage remote-feature-flag-controller.test.ts — all 53 tests pass
  • Threshold flags without thresholdName return the value directly and leave featureFlagThresholdGroups empty
  • Threshold flags with thresholdName return the value directly and populate featureFlagThresholdGroups
  • Stale featureFlagThresholdGroups entries are cleaned up when flags are removed from the server response

Made with Cursor

…y and track threshold groups

Threshold feature flags now expose the selected value directly instead of a
{name, value} wrapper. When thresholdName is present on the selected group,
store the mapping in featureFlagThresholdGroups on controller state.

Co-authored-by: Cursor <cursoragent@cursor.com>
@asalsys asalsys requested review from a team as code owners June 26, 2026 14:03
@asalsys asalsys temporarily deployed to default-branch June 26, 2026 14:03 — with GitHub Actions Inactive
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.

1 participant