Roope's RFC: Slack thread | Confluence design note | PR #112752
cms_component_usages is a PG table that indexes which components are used in which RTF field of which CMS item (CMSAUTH-5260). Collection schemas live in Mongo, usages in PG, so they can drift. The most common reads are cross-collection ("where is component X used?"), so read-time filtering via per-result PG-to-Mongo liveness checks is too expensive.
On the delete path, a genuine PG failure is currently swallowed (log-and-continue). The Mongo collection gets deleted anyway, and the PG rows (usage rows + item table) are orphaned permanently, with no self-healing path.
Roope proposes "authoritative table + reconciliation" and asks whether we agree, or if there's a cheaper read-side angle.
Roope's framing is right. Points to make in the thread:
-
Delete-path: propagate, don't swallow. A silent orphan means both usage rows AND the item table leak. Since this table now drives component governance ("is it safe to delete this component?"), silently wrong answers are a real product risk. Fail and retry is better than silent drift.
-
Reconciliation is the backstop, not the primary fix. Fix the delete path first. The sweep covers edge cases (rare delete failures, the "never-edited-again collection" update-path gap), but shouldn't be the reason to keep the swallow.
-
The cheap collection-existence read filter (step 4) is worth doing. The "where is X used" panel likely already knows the live collection set. Dropping rows whose
collection_iddoesn't exist is basically free (in-memory set intersection). Defense-in-depth for the window between orphan creation and sweep execution. -
Flag for reconciliation sweep: it needs to query Mongo for the live collection/field set. Batch and rate-limit per database so it doesn't spike Mongo read load across the fleet. The prune logic it reuses is scoped to a single collection, but the sweep iterates across all collections in a database.
- Observability (metrics/counters on swallowed failures)
- Reliable delete-path cleanup (propagate instead of swallow)
- Periodic reconciliation sweep (reuses existing prune logic)
- Optional cheap collection-existence read filter
- Internal remediation endpoint (admin panel button, last)