[FF] organization_maintenance_enforcement -- Organization Maintenance Mode enforcement

Summary

Roll out Organization Maintenance Mode enforcement currently behind the organization_maintenance_enforcement feature flag.

Part of &20404. Design: ADR 010 — Organization Maintenance Mode.

Note

Supersedes #603377 (closed), which tracked the same rollout under the flag's previous name (organization_read_only_enforcement). The flag is renamed in #614066 (closed) / !250667 (merged). The flag has never been enabled in any environment, so no rollout state carries over.

Flag

  • Name: organization_maintenance_enforcement
  • Type: gitlab_com_derisk, default-off
  • Gates: request blocking for Organizations in a maintenance state, across controllers, REST API, GraphQL, GitAccess, and Container Registry auth
  • Scope: environment- and Organization-scoped (Organization actor), so rollout can proceed cohort-by-cohort

Note

Not a prerequisite: the instance-level fallback in Container Registry auth (#618031) is deferred while the package team freezes registry changes for the artifact registry deploy. The branch it removes is unreachable — projects.organization_id is NOT NULL and is the table's sharding key — so it cannot be evaluated during rollout.

What could go wrong?

  • Blast radius is per-Organization (the flag takes an Organization actor), except that enabling it for an Organization currently in a maintenance state blocks all requests for it, reads included — this is the intended behavior of the current iteration (#607966 (closed) / !250225 (merged)), not a bug. No Organization is in a maintenance state in production today, so enabling the flag is a no-op until an operator transitions one.
  • Prerequisite before enabling for any Organization with real users: authentication is not exempted in this iteration (#602813 (closed) is deferred), so a user of an Organization in a maintenance state cannot sign in. Enable only against Organizations where that is acceptable (internal/test), or land the auth exemption first.
  • One remaining instance-level check in Container Registry auth is removed in #618031; until then, a flag enablement there is theoretically cell-wide rather than per-Organization (the branch is unreachable in practice — see that issue).
  • Dashboards to watch: blocked-request rates and 503/403 responses attributable to the enforcement layers.

Rollout

Run all production /chatops in #production and cross-post results to #g_organizations.

Non-production

/chatops gitlab run feature set organization_maintenance_enforcement true --dev --pre --staging --staging-ref

Production — target specific Organizations rather than a percentage, since the actor is an Organization and the intended use is operator-initiated per-Organization freezes:

/chatops gitlab run feature set --group=<test-org-root-group> organization_maintenance_enforcement true
  • Land the state + flag rename (#614066 (closed) / !250667 (merged)) — merged 2026-08-21; flag is organization_maintenance_enforcement, no references to the old name remain
  • Enable on non-production environments and verify dark (no Organization in a maintenance state → no behavior change) — enabled on dev, gstg, gstg-ref, and pre on 2026-08-25
  • Verify enforcement end-to-end against an internal/test Organization transitioned into maintenance_initialization / maintenance
  • Enable globally on production (gprd) — enabled 2026-08-31, no scopes set, dark until an Organization is transitioned (gitlab-com/gl-infra/feature-flag-log#63440)
  • Expand alongside the existing Organizations rollout cohorts
  • Monitor blocked-request logs and dashboards
  • Default-enable once confidence is reached

Before global rollout

  • Docs + version history updated
  • Operator runbook exists (#603919) — required before an operator can be asked to use this
  • Change management issue opened, if required
  • Default-off on Self-Managed and Dedicated (instance-wide Maintenance Mode remains the right tool there, see ADR 007) — flag is gitlab_com_derisk with default_enabled: false, so this holds structurally

Cleanup

/chatops gitlab run release check <merge-request-url> <milestone>
/chatops gitlab run feature delete organization_maintenance_enforcement --dev --pre --staging --staging-ref --production

Rollback

/chatops gitlab run feature set organization_maintenance_enforcement false
/chatops gitlab run feature set organization_maintenance_enforcement false --dev --pre --staging --staging-ref

Related: #614066 (closed) / !250667 (merged) (rename), #618031 (registry fallback), #603377 (closed) (superseded), #602813 (closed) (auth exemption, deferred), #603919 (operator runbook).

Edited by Chen Zhang