Runbook — retiring ReleaseOrchestrator’s topology copy (RO migration 009)

009_release_orchestrator_retire_topology_inventory_projection.sql drops ReleaseOrchestrator’s copy of the nine release.topology_* inventory tables. Platform owns that projection in its own database (098_v1_release_topology_inventory_projection.sql), and nothing in ReleaseOrchestrator writes or reads the RO copy. The migration refuses with SQLSTATE 55000 while any of the nine holds a row. On an estate where the copy still holds rows, ReleaseOrchestrator therefore stops at startup on 009.

Run this procedure before the first ReleaseOrchestrator redeploy that carries 009. It is the only step that removes data, and it is an operator decision. The migration never removes rows.

1. Measure the RO copy (read-only)

In ReleaseOrchestrator’s own database (stellaops_release_orchestrator):

SELECT 'region' AS t, count(*) FROM release.topology_region_inventory
UNION ALL SELECT 'environment', count(*) FROM release.topology_environment_inventory
UNION ALL SELECT 'target', count(*) FROM release.topology_target_inventory
UNION ALL SELECT 'host', count(*) FROM release.topology_host_inventory
UNION ALL SELECT 'agent', count(*) FROM release.topology_agent_inventory
UNION ALL SELECT 'promotion_path', count(*) FROM release.topology_promotion_path_inventory
UNION ALL SELECT 'workflow', count(*) FROM release.topology_workflow_inventory
UNION ALL SELECT 'gate_profile', count(*) FROM release.topology_gate_profile_inventory
UNION ALL SELECT 'sync_watermarks', count(*) FROM release.topology_sync_watermarks;

SELECT count(*), min(last_synced_at), max(last_synced_at) FROM release.topology_sync_watermarks;

SELECT relname, n_tup_ins, n_tup_upd, n_tup_del
FROM pg_stat_user_tables
WHERE schemaname = 'release' AND relname LIKE 'topology_%' ORDER BY relname;

If all nine are empty, stop here: 009 drops them and startup continues.

2. Prove the copy is stale (read-only)

Run the watermark query again in Platform’s database (stellaops_platform). The RO copy is a stale copy when all three hold:

If any of the three fails, do not continue. Something is writing RO’s copy, which contradicts the ownership record. Stop and escalate.

3. Remove the stale copy

In stellaops_release_orchestrator only, with ReleaseOrchestrator stopped or not yet redeployed:

BEGIN;
TRUNCATE release.topology_target_inventory, release.topology_host_inventory,
         release.topology_agent_inventory, release.topology_promotion_path_inventory,
         release.topology_workflow_inventory, release.topology_gate_profile_inventory,
         release.topology_sync_watermarks, release.topology_environment_inventory,
         release.topology_region_inventory;
COMMIT;

Never run this in stellaops_platform. Platform’s copy is the live projection.

4. Redeploy and verify

Redeploy ReleaseOrchestrator. Its startup ledger then records 009, and SELECT to_regclass('release.topology_region_inventory') in RO’s database returns NULL. release.topology_point_status and the source topology (regions, environments, targets) are untouched.

Measured on the lab estate (2026-09-23)

The RO copy held 68 rows: region 1, environment 4, target 1, host 1, agent 2, promotion_path 3, workflow 4, gate_profile 4, sync_watermarks 48. Every watermark read last_synced_at 2026-08-22 12:13:25, and pg_stat_user_tables showed 0 inserts, updates and deletes on all nine. Platform’s 48 watermarks were synced that day. This estate therefore needs step 3 before its first ReleaseOrchestrator redeploy carrying 009.