.ai/principles/distilled/feature-flags.md
default_enabled: false).config/initializers/* or at class level).Feature.current_request as actor with percentage-of-actors instead.group.root_ancestor as the actor when flag state must be consistent across an entire group hierarchy.Feature.enabled? for the same flag unless you are certain it won't cause inconsistent results within a request.:instance as the actor only when a feature is tied to an entire instance and no other actor type applies.Feature.enabled? and avoid Feature.get.~"feature flag" label to MRs that introduce, update state of, or remove a feature flag.rspec:feature-flags job).gitlab-org/gitlab if there is no documentation._mvc, _alpha, _beta in flag names.disable in flag names; prefer hide_, remove_, or disallow_ prefixes instead.bin/feature-flag (or bin/feature-flag --ee for EE-only).name, description, type, default_enabled, introduced_by_url, milestone, group.milestone value — read it from the VERSION file in the repo root and use the MAJOR.MINOR portion only (e.g., if VERSION contains 19.0.0-pre, set milestone: "19.0")default_enabled: false for gitlab_com_derisk, wip, and experiment types (setting it to true has no effect or is forbidden for these types).beta and ops type flags in the All feature flags in GitLab page.beta and ops type flags in the All feature flags in GitLab page; for ops flags, also maintain an associated operational runbook describing when the flag can be used.gitlab_com_derisk and beta flags..patch file alongside the YAML to enable automated removal via gitlab-housekeeper.log_state_changes: true in the YAML definition when you need to log feature flag state changes (searchable in Kibana via json.feature_flag_states).gitlab_com_derisk for short-lived deployment de-risking flags (max 2 months lifespan).wip for hiding incomplete multi-MR features until fully implemented (max 4 months lifespan); transition to gitlab_com_derisk or beta before enabling.beta when a feature may have scalability concerns or is not yet a complete MVC (max 6 months lifespan).ops for long-lived operational control flags; evaluate every 12 months and update milestone to confirm continued use.experiment for A/B testing on GitLab.com (max 6 months lifespan); create rollout issue from the Experiment Rollout template.development type; use gitlab_com_derisk, wip, or beta instead.Feature.enabled? and Feature.disabled?.Project.actor_from_id(project_id) instead of Project.find(project_id) when the model is only needed for the feature flag check.experiment, worker, undefined types), pass type: explicitly to Feature.enabled?, Feature.disabled?, and push_frontend_feature_flag.FeatureGate in any model that needs to be used as a feature flag actor.push_frontend_feature_flag in a before_action scoped to a project or user actor.gon.features.vimBindings), not snake_case.if: filter in lib/gitlab/event_store/subscriptions/feature_subscriptions.rb; DO NOT subscribe to all feature flag changes globally.FeatureFlagModifiedEvent are idempotent, as multiple enable/disable calls with the same author may produce multiple events.FeatureFlagModifiedEvent for percentage-based rollout methods (Feature.enable_percentage_of_actors and Feature.enable_percentage_of_time); only Feature.enable and Feature.disable publish events, and only when a state change occurs.other type).true — they are enabled by default in the test environment.stub_feature_flags(flag_name: false) to test the disabled state; place the stub in a before hook within a self-contained context.stub_feature_flags over Feature.enable* for test setup; use Feature.enable_percentage_of_time or Feature.enable_percentage_of_actors only when testing percentage rollout behavior.have_pushed_frontend_feature_flags matcher to verify push_frontend_feature_flag added the flag to HTML.stub_feature_flag_gate to create a custom actor for actor-specific flag testing in specs.stub_feature_flags: false unless specifically testing Flipper's interaction with ActiveRecord.experiment(:name, actor: current_user) as context but the corresponding issue mentions tracking of namespace-based activation events, assignment should happen based on namespace or actor + namespaceexperiment(:name, actor: current_user).track(:assignment, namespace: group)run_sidekiq_jobs_{WorkerName} (worker-type flag) to defer Sidekiq jobs during incidents; remove the flag after the worker is deemed safe.drop_sidekiq_jobs_{WorkerName} only when jobs are certain to not need future processing; note it takes precedence over run_sidekiq_jobs_{WorkerName}.ops flag to an application setting.default_enabled: from the feature flag YAML definition.Gitlab::Database::MigrationHelpers::FeatureFlagMigratorHelpers helpers in the migration; DO NOT use Feature.enabled? or Feature.disabled? inside migrations.true or false — flags set for a percentage or specific actor will use the default value.For the full picture, see: