CtrlK
BlogDocsLog inGet started
Tessl Logo

testland/feature-flag-test-matrix-reference

Pure-reference catalog of feature-flag test matrix design. Defines the flag-state combinatorics problem (N flags × M variants × K user-segments = N×M×K test cases), the canonical coverage strategies (pairwise interaction coverage; default-only smoke; full matrix; risk-driven matrix), the kill-switch + percentage-rollout test patterns, and the relationship between flags + experiments (flags toggle behaviour; experiments measure outcome). Use when designing the flag-test surface for a new project or auditing existing flag-test coverage.

77

Quality

97%

Does it follow best practices?

Run evals on this skill

Adds up to 20 points to the overall score

View guide

SecuritybySnyk

Passed

No findings from the security scan

Overview
Quality
Evals
Security
Files
name:
feature-flag-test-matrix-reference
description:
Pure-reference catalog of feature-flag test matrix design. Defines the flag-state combinatorics problem (N flags × M variants × K user-segments = N×M×K test cases), the canonical coverage strategies (pairwise interaction coverage; default-only smoke; full matrix; risk-driven matrix), the kill-switch + percentage-rollout test patterns, and the relationship between flags + experiments (flags toggle behaviour; experiments measure outcome). Use when designing the flag-test surface for a new project or auditing existing flag-test coverage.

feature-flag-test-matrix-reference

Overview

A codebase with N feature flags, each having M variants, and users in K segments, has N × M × K possible flag-state-segment combinations. At realistic numbers (50 flags, 2 variants each, 5 segments) that's 500 - and at 50 flags with 3 variants and 10 segments, it's 1500. Testing every combination is infeasible, so the matrix has to be sampled deliberately rather than enumerated.

This skill is a pure reference consumed by the SDK-test + coverage-builder skills.

When to use

  • Designing the test surface for a new flag-heavy product.
  • Auditing existing flag-test coverage - are critical combinations covered?
  • PR review of a new flag - does it create a coverage gap?
  • Investigating an "only happens with flag X + flag Y on" incident.

How to use

  1. Inventory the flags: list every flag, its variant count (M), and the user segments (K) it targets.
  2. Size the problem: compute N × M × K to confirm full enumeration is infeasible and sampling is required.
  3. Discover interactions: mark flags as inert (independent) or known-interacting (auth + permissions, billing + plan-tier), pulling from a risk register where one exists.
  4. Pick a coverage strategy from the five below - default-only smoke, per-flag isolation, pairwise, full matrix, or risk-driven - matching the flag set's risk.
  5. Add the special flag-state categories (kill-switch, percentage-rollout, sticky-assignment, default-on-error) as their own tests.
  6. Layer the resulting cases across unit, integration, E2E, and production-smoke.
  7. Hand the matrix to the platform SDK skill (launchdarkly-testing, unleash-testing, flagsmith-testing, growthbook-testing) to implement each case.

The combinatorics

VariableTypical scale
Total flags in codebase20-500
Variants per flag2 (most), 3-5 (experiments), 10+ (multivariate)
User segments5-20 (free, paid, enterprise, internal, beta, etc.)
Combinatorial totalQuickly enters thousands

Insight: most flag combinations are inert (independent). Only a small subset interact - the test matrix should target interactions.

Five coverage strategies

1. Default-only smoke

Test only the default-value combination ("all flags off" or "all flags at default"). Fast but misses everything.

Use when: flag-heavy codebase where defaults change rarely.

2. Per-flag isolation

For each flag, test default + each variant in isolation. N × M tests; ignores interactions.

Use when: flags are mostly independent (UI tweaks, language strings, low-risk).

3. Pairwise interaction

Test every pair of flags (combinatorial 2-way coverage). Per NIST SP 800-142 on combinatorial testing, pairwise catches ~67% of real defects with O(N²) combinations.

Use when: flags are known-interacting (auth + permissions, billing + plan-tier).

Implementation: tools like pict (Microsoft) generate the pairwise matrix from a flag inventory.

4. Full matrix

Every combination. N^M tests for boolean flags.

Use when: small (≤10) flag count with strong interaction; financial / regulatory paths.

5. Risk-driven

Custom matrix targeting (flag, segment) cells with known risk (per a risk register per risk-matrix in the qa-process plugin).

Use when: any non-trivial codebase. Best in practice.

Special flag-state test categories

CategoryTest
Kill-switchSetting flag → off must halt the feature within N seconds (cache TTL)
Percentage rolloutFlag at 10% → ~10% of users in 'on' bucket; SDK assignment stable per user
Targeted rolloutTargeting region=EU → only EU users get treatment
Sticky assignmentSame user → same variant across sessions and re-launches
Override hierarchyUser-specific override > segment override > default
Default-on-errorSDK fails / network down → default value returned
Fast-deactivateToggle flag off → live users see new state on next evaluation

These are per-platform behaviours (LaunchDarkly, Unleash, Flagsmith, GrowthBook implement them differently); test per platform per the SDK skills.

Flag-test layering

Tests should run at multiple layers:

LayerCoverage
UnitResolver / handler logic gated on flag value (mock SDK)
IntegrationSDK + handler together (test SDK against local-eval / fixture)
E2EReal flag toggle → real user sees the change
Production smokeAfter flag change → assert expected behaviour live

Flag-experiment distinction

Per ab-test-validity-checklist (in the qa-experimentation plugin):

FlagExperiment
Toggles behaviourMeasures outcome
Boolean / multi-variantMulti-arm with metrics
Test the behaviour changeTest the assignment + outcome correlation
Ship decision on engineering judgmentShip decision on statistical result

A feature flag can power an experiment (the flag is the allocation mechanism), but tests are layered: flag tests verify correct behaviour per variant; experiment tests verify assignment + analytics.

Worked example

A billing service has 3 boolean flags - new_checkout, annual_discount, tax_engine_v2 - across 3 segments (free, paid, enterprise). The team knows annual_discount and tax_engine_v2 interact: a discount changes the taxable amount.

  1. Inventory: 3 flags, 2 variants each, 3 segments; the full flag-state-by-segment cross-product is too large to enumerate.
  2. Interaction discovery marks the annual_discount × tax_engine_v2 pair as known-interacting; new_checkout is a UI change treated as independent.
  3. Strategy: risk-driven. Per-flag isolation covers new_checkout; a pairwise cell covers (annual_discount on, tax_engine_v2 on) on the paid and enterprise segments where money moves.
  4. Special categories: a kill-switch test asserts toggling tax_engine_v2 off reverts to v1 within the cache TTL; a sticky-assignment test asserts the annual_discount percentage rollout keeps each user in the same bucket across sessions.
  5. Layering: unit tests exercise the tax resolver per flag value; an E2E test toggles tax_engine_v2 and asserts an enterprise invoice total.

Result: a handful of targeted cases instead of the full cross-product, with the discount × tax interaction covered explicitly.

Anti-patterns

Anti-patternWhy it failsFix
Test only default-value pathMisses every flag-on casePer-flag isolation minimum
Mock the SDK to return constantMisses targeting / rollout logicLocal-eval mode or fixture-based SDK
Same test for every flag combinationSlow; flaky; opaque failuresPer-combination assertion logs
No kill-switch testProduction incident has no rehearsed responseTest deactivation latency
Don't test percentage-rollout sticky-assignmentRollout produces non-deterministic UXPer ab-test-validity-checklist
Tests assume flag-on defaultReal default-off behaviour untested in CITest both paths
No cleanup test for removed flagsStale-flag accumulates per flag-removal-runbook-authorPeriodic stale-flag audit
Pairwise without flag-interaction discoverySome pairs spuriously interactCouple with risk-register input

Limitations

  • Pairwise misses 3-way+ interactions. Some real-world bugs need 3-way coverage.
  • Real-world matrices have ordering effects. Flag A enabled THEN flag B may differ from B then A; test ordering needs separate coverage.
  • Coverage tooling lags. PICT / ACTS exist but integration with flag platforms is bespoke.
  • Stale flags pollute the matrix. Cleanup pairs with flag-removal-runbook-author.

References

  • LaunchDarkly flag-testing strategy: launchdarkly.com/blog/.
  • NIST SP 800-142 (combinatorial testing): csrc.nist.gov/publications/detail/sp/800-142/final.
  • GrowthBook test docs: docs.growthbook.io/lib/node.
  • Sibling catalogs: flag-state-coverage-builder, flag-removal-runbook-author.
  • Consumed by: launchdarkly-testing, unleash-testing, flagsmith-testing, growthbook-testing.
  • Cross-plugin: ab-test-validity-checklist, feature-flag-test-harness.
Workspace
testland
Visibility
Public
Created
Last updated
Publish Source
GitHub
Badge
testland/feature-flag-test-matrix-reference badge