Propagation-based state inheritance for namespaces
## Overview
This epic tracks the implementation of switching from **lookup-based to propagation-based state inheritance** for GitLab's namespace hierarchy (Organization > Group > Subgroup > Project), as described in [ADR 003: State Propagation Model](https://handbook.gitlab.com/handbook/engineering/architecture/design-documents/group_and_project_operations_and_state_management/decisions/003_state_propagation_model/) and [MR !19153](https://gitlab.com/gitlab-com/content-sites/handbook/-/merge_requests/19153).
### Problem
The current lookup-based approach determines effective state by traversing up the ancestor hierarchy at read time. This causes:
- Read-time query overhead on every state check
- Inconsistent state inference across descendants
- No clear propagation rules through the hierarchy
- Caching complexity to mitigate read performance
### Solution
Propagate states (`active`, `archived`, `deletion_scheduled`) to all descendants when set on a namespace, enabling fast reads via simple column comparisons without ancestor traversal.
### DRI
@aakriti.gupta
---
## Implementation Outline
## Key Technical Decisions
## References
- [ADR 003: State Propagation Model MR !19153](https://gitlab.com/gitlab-com/content-sites/handbook/-/merge_requests/19153)
- [ADR 001: Unified State Management](https://handbook.gitlab.com/handbook/engineering/architecture/design-documents/group_and_project_operations_and_state_management/decisions/001_unified_state_management/)
- [ADR 006: State Preservation](https://handbook.gitlab.com/handbook/engineering/architecture/design-documents/group_and_project_operations_and_state_management/decisions/006_state_preservation/)
- [Tree Iterator Documentation](https://docs.gitlab.com/development/database/poc_tree_iterator/)
- [Transactional Outbox Pattern](https://microservices.io/patterns/data/transactional-outbox.html)
<!-- STATUS NOTE START -->
## Status 2026-08-13
:clock1: **total hours spent this week by all contributors**: 10h
_(Estimate: in line with last week's 10h. Team was partially OOO; the week's focus was landing the core worker and opening the next follow-ups.)_
:tada: **achievements**:
- **Core propagation worker merged — the epic's main bottleneck is cleared:** [!242220](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/242220) (`Namespaces::StatePropagationWorker`, [#599298](https://gitlab.com/gitlab-org/gitlab/-/work_items/599298)) merged. This was the single blocker every remaining Phase 3–6 issue was funnelling through last week, so its landing unblocks the rest of the epic.
- **State-preservation integration opened for review:** [!243865](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/243865) ([#599299](https://gitlab.com/gitlab-org/gitlab/-/work_items/599299)) extends the worker to preserve a descendant's previous state so it can be restored if a parent operation is cancelled ([ADR 006](https://handbook.gitlab.com/handbook/engineering/architecture/design-documents/group_and_project_operations_and_state_management/decisions/006_state_preservation/)) — the first follow-up to start now that the worker is in.
- **Reconciliation cron worker queued behind the core worker:** [!242221](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/242221) ([#599300](https://gitlab.com/gitlab-org/gitlab/-/work_items/599300)) is ready to progress now that its dependency has merged; it catches lost or stalled propagation jobs.
:issue-blocked: **blockers**:
- The Phase 4 outbox callback [!247075](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/247075) ([#599305](https://gitlab.com/gitlab-org/gitlab/-/work_items/599305)) was **closed** rather than merged and needs a replacement MR to keep Phase 4 moving. Deferring domain events/webhooks ([#599308](https://gitlab.com/gitlab-org/gitlab/-/work_items/599308)) remains blocked on that callback landing.
:arrow_forward: **next**:
- Land the state-preservation integration [!243865](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/243865) and the reconciliation cron worker [!242221](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/242221) now that the core worker has merged.
- Re-open/replace the Phase 4 after_transition callback [#599305](https://gitlab.com/gitlab-org/gitlab/-/work_items/599305), then proceed to event/webhook deferral [#599308](https://gitlab.com/gitlab-org/gitlab/-/work_items/599308).
- Resume [Phase 6](https://gitlab.com/groups/gitlab-org/-/work_items/21925) observability work — metrics [#599314](https://gitlab.com/gitlab-org/gitlab/-/work_items/599314) and structured logging [#599315](https://gitlab.com/gitlab-org/gitlab/-/work_items/599315).
_Copied from https://gitlab.com/groups/gitlab-org/-/epics/21607#note_3680084129_
<!-- STATUS NOTE END -->
epic