Skip to content

Commit 670a8a5

Browse files
docs: document enrollmentsMap 12-month retention limit (#820)
* docs: document enrollmentsMap 12-month retention limit Because * The enrollmentsMap targeting attribute includes both active and inactive enrollment records, but inactive records are permanently deleted after 12 months (365.25 days) from the original enrollment date * This caused a production issue where a rollout depending on a holdback via enrollmentsMap started losing clients when the holdback's enrollment records aged out of the store * The existing documentation did not mention the retention behavior or the difference between enrollmentsMap and activeExperiments/activeRollouts This commit * Expands the enrollmentsMap entry in the targeting attributes table * Adds a detailed subsection explaining enrollmentsMap behavior, the 12-month retention limit, and how to handle holdback transitions * Adds a comparison table showing the differences between the three enrollment-related targeting attributes * docs: clarify clone-and-replace pattern for holdback transitions Because * Targeting cannot be modified on already-launched experiments/rollouts This commit * Replaces "update dependent targeting expressions" with the correct workflow: clone the dependent experiment with updated targeting, launch the clone, then end the original * docs: clarify 12-month limit only applies after experiment ends Because * Active enrollments are never cleaned up regardless of age * The previous wording could be misread as a hard 12-month cap on all enrollment records This commit * Clarifies that enrollmentsMap entries persist indefinitely while the experiment is live * Specifies the 12-month cleanup only starts after the experiment ends * Notes that clients who enrolled earlier are affected first * Updates the retention column in the comparison table * docs: remove prescriptive adaptation pattern from enrollmentsMap section Because * The docs should describe behavior, not recommend specific workflows This commit * Removes the holdback transition example and clone-and-replace guidance * docs: link to _cleanupOldRecipes() source for 12-month retention Because * Review feedback from Beth to link to the actual code This commit * Adds a Searchfox link to _cleanupOldRecipes() in ExperimentStore.sys.mjs * fix: add missing resolved/integrity for webpack in yarn.lock Because * The webpack entry in yarn.lock was missing its resolved URL and integrity hash, causing yarn to install 5.106.0 instead of the pinned 5.89.0 * webpack 5.106.0 has a breaking change in ProgressPlugin that is incompatible with webpackbar 5.0.2, failing the build This commit * Adds the resolved URL and integrity hash for webpack 5.89.0 * docs: use pinned revision link for _cleanupOldRecipes Because * The mozilla-central source link could shift as lines are added/removed This commit * Uses a specific revision hash in the Searchfox link so it stays stable
1 parent dc21b35 commit 670a8a5

2 files changed

Lines changed: 29 additions & 3 deletions

File tree

docs/platform-guides/desktop/targeting.md

Lines changed: 27 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -169,9 +169,9 @@ os.isMac
169169

170170
| Attribute | Type | Description | Example |
171171
|-----------|------|-------------|---------|
172-
| `activeExperiments` | `string[]` | Currently enrolled experiment slugs | `'my-experiment' in activeExperiments` |
173-
| `activeRollouts` | `string[]` | Currently enrolled rollout slugs | `!('some-rollout' in activeRollouts)` |
174-
| `enrollmentsMap` | `array` | All enrollments as `{experimentSlug, branchSlug}` entries | Used for branch-level exclusion |
172+
| `activeExperiments` | `string[]` | Currently enrolled experiment slugs (active only) | `'my-experiment' in activeExperiments` |
173+
| `activeRollouts` | `string[]` | Currently enrolled rollout slugs (active only) | `!('some-rollout' in activeRollouts)` |
174+
| `enrollmentsMap` | `object` | Map of experiment/rollout slug → branch slug for all enrollments (active and inactive). See [enrollmentsMap details](#enrollmentsmap) below. | `enrollmentsMap['my-holdback'] == 'treatment'` |
175175

176176
### New Tab & Home Page
177177

@@ -439,6 +439,30 @@ userMonthlyActivity|length >= 14 && userMonthlyActivity|length < 21
439439
!('other-experiment-slug' in activeExperiments)
440440
```
441441

442+
### Branch-level dependency with `enrollmentsMap` {#enrollmentsmap}
443+
444+
`enrollmentsMap` is an object that maps experiment/rollout slugs to branch slugs. Unlike `activeExperiments` and `activeRollouts` (which only contain currently active enrollments), `enrollmentsMap` includes **both active and inactive** enrollment records. This makes it useful for targeting based on a client's enrollment history — for example, requiring that a client was previously enrolled in a specific branch of a holdback experiment.
445+
446+
```
447+
// Require enrollment in the delivery branch of a holdback
448+
enrollmentsMap['long-term-holdback-2026-growth-desktop'] == 'delivery'
449+
```
450+
451+
:::warning 12-Month Retention After Ending
452+
Enrollment records stay in `enrollmentsMap` **indefinitely while the experiment/rollout is live** — there is no time limit for active enrollments. The retention limit only applies after an experiment **ends**: once an enrollment becomes inactive, its record is permanently deleted from the client's store **12 months (365.25 days) after the original enrollment date** (see [`_cleanupOldRecipes()`](https://searchfox.org/firefox-main/rev/62b11cf9d978f8c6f8144156feebf42af5d71cf9/toolkit/components/nimbus/lib/ExperimentStore.sys.mjs#390)). Once deleted, the key is removed from `enrollmentsMap` and any targeting expression that references it will no longer match.
453+
454+
This means if experiment B's targeting depends on enrollment in experiment A via `enrollmentsMap`, and experiment A ends, you have a **12-month window** (from when each client originally enrolled in A) before clients start losing the record. After that point, clients will begin unenrolling from experiment B with `targeting-mismatch` as their `enrollmentsMap` entries for experiment A are cleaned up. Clients who enrolled earlier in experiment A's lifetime will be affected first.
455+
456+
:::
457+
458+
**Key differences between enrollment attributes:**
459+
460+
| Attribute | Includes Active | Includes Inactive | Provides Branch | Retention |
461+
|-----------|:-:|:-:|:-:|---|
462+
| `activeExperiments` |||| Current session only |
463+
| `activeRollouts` |||| Current session only |
464+
| `enrollmentsMap` |||| Indefinite while active; 12 months from enrollment date after ending |
465+
442466
## Recorded Targeting Context (Telemetry)
443467

444468
Firefox records a snapshot of all the targeting attribute values listed above in the `nimbus-targeting-context` ping, which lands in BigQuery at `mozdata.firefox_desktop.nimbus_targeting_context`. This is used for:

yarn.lock

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8121,6 +8121,8 @@ webpack-sources@^3.2.2, webpack-sources@^3.2.3:
81218121

81228122
"webpack@^4.0.0 || ^5.0.0", "webpack@^4.37.0 || ^5.0.0", webpack@^5.0.0, webpack@^5.1.0, webpack@^5.20.0, webpack@^5.73.0, "webpack@>= 4", webpack@>=2, "webpack@>=4.41.1 || 5.x", "webpack@3 || 4 || 5":
81238123
version "5.89.0"
8124+
resolved "https://registry.npmjs.org/webpack/-/webpack-5.89.0.tgz"
8125+
integrity sha512-qyfIC10pOr70V+jkmud8tMfajraGCZMBWJtrmuBymQKCrLTRejBI8STDp1MCyZu/QTdZSeacCQYpYNQVOzX5kw==
81248126
dependencies:
81258127
"@types/eslint-scope" "^3.7.3"
81268128
"@types/estree" "^1.0.0"

0 commit comments

Comments
 (0)