## Summary Buzz is moving database invariants from triggers and foreign keys into application-owned transaction protocols. This PR adds the first transition foundations while preserving all current database backstops. - Add a shared community-write lock for single-community writer transactions, and make deletion lifecycle transitions take the matching exclusive lock. A supported serving transaction never spans communities. - Add shared event-writer and exclusive replica-probe lock ordering around the existing heartbeat publication model. - Document the supported writer contract, reviewed backfill path, and transition gates. - Keep one replica-floor publication concept and remove an unrelated reconciliation-script edit found during review. This narrows the change rather than adding parallel protocols. The blast radius is limited to new opt-in writer helpers plus lock acquisition in deletion and replica probing. Existing trigger and GUC enforcement remains authoritative, so callers can migrate in later pull requests. ### Related issue [BUZZ-175](https://linear.app/squareup/issue/BUZZ-175). This is the first implementation slice from the OSC migration plan. ### Testing No manual testing. CI covers the Rust checks and database tests added here. Generated with [Codex](https://openai.com/codex) --------- Signed-off-by: tornquist <tornquist@squareup.com> Co-authored-by: Codex <noreply@openai.com>
1321 cutover: single-community → multi-tenant
1321_backfill_default_community.sql is a one-off operator script, not a
startup migration. It takes a pre-1321 (single-community) Buzz Postgres to the
1321 multi-tenant schema, assigning every existing row to one default community
derived from the deployment host.
It is not embedded in the relay binary. The relay's
sqlx::migrate!embeds onlymigrations/0001_initial_schema.sql— the consolidated 1321 schema. Fresh deployments need only that; this script exists solely to carry existing pre-1321 data across the rewrite. (It uses psql client features —\set,\ir,:'var'interpolation,\gset— that the embedded sqlx migrator cannot run, which is why it must live here and not undermigrations/.)
When you need it
Only when upgrading a Postgres that already holds pre-1321 single-community
data to 1321. A brand-new deployment does not run this — it provisions
from migrations/0001_initial_schema.sql (or schema/schema.sql) directly.
Supported writer contract during transition
Outside this one-off cutover, direct owner SQL mutation is not a supported steady-state path unless explicitly reviewed.
- Reviewed backfills and reconciliations should use relay-owned transaction and lock protocols where they exist (one community fence per transaction and replica-floor shared/exclusive lock ordering).
- If a workflow cannot use those protocols yet, execute it under an explicitly reviewed procedure that keeps replica routing fences closed for the run.
- Existing trigger/function backstops remain the commit-time authority during this transition. Their removal requires separate coverage and fleet gates; this cutover does not authorize it.
- Role separation is deliberate: schema reconciliation scripts carry schema convergence only; serving admission/fencing semantics remain in runtime/store code paths with startup verification and metrics.
Preconditions
- The DB is pristine pre-1321: no
communitiestable, nocommunity_idcolumns, no leftoverlegacyschema. The script's guard refuses to run otherwise (already-migrated, partially-migrated, or failed-prior-run states all raise and abort — see the guard block at the top of the script). - Take a
pg_dump/ PVC snapshot first. There is no down-path. The snapshot is the rollback.
Run it
The whole script runs in one transaction (all-or-nothing). Pass the
deployment host as :host; it is normalized exactly as the relay normalizes a
community host (rtrim(lower(host), '.')).
psql "$DATABASE_URL" \
-v host="'your-deployment-host.example.com'" \
-v ON_ERROR_STOP=1 \
-f scripts/cutover/1321_backfill_default_community.sql
-f (not stdin) matters: the script \ir-includes
../../migrations/0001_initial_schema.sql relative to its own location, so
it resolves the canonical 1321 schema regardless of your cwd.
What it does
- Renames all pre-1321 tables and enum types aside into a
legacyschema. \ir-includes the repo's0001verbatim → the correct 1321 schema in a cleanpublic(structurally identical to a fresh 1321 DB by construction — no hand-transcription).- Creates the one default community from
:host. - Copies every row forward, stamped with that
community_id(search_tsvregenerates as GENERATED; new-in-1321 columns default NULL). DROP SCHEMA legacy CASCADE.
After it commits
Boot the 1321 relay with BUZZ_AUTO_MIGRATE=false. The schema is already
correct; the relay's idempotent boot-time ensure_configured_community /
allowlist→relay_members backfill finds this community and no-ops.
If you want the relay's sqlx migrator to consider 0001 already applied (so a
later BUZZ_AUTO_MIGRATE=true boot doesn't try to re-run it), seed its
_sqlx_migrations row to match a fresh 1321 install:
-- version 1, description 'initial schema'; checksum must match the embedded 0001.
-- Easiest: diff _sqlx_migrations against a freshly-migrated 1321 DB and copy the row.
This is not required for correct operation — a fresh 0001 run against the
already-correct schema is a no-op only if the migrator's checksum matches, so
prefer leaving BUZZ_AUTO_MIGRATE=false unless you have a reason to seed.
Verify (post-commit, outside the txn)
SELECT count(*) FROM communities; -- expect 1
SELECT count(*) FROM events WHERE community_id IS NULL; -- expect 0
SELECT to_regnamespace('legacy'); -- expect NULL (gone)
For a stronger guarantee, take a constraint/trigger/index/column diff of this DB against a freshly-migrated 1321 DB — it should be empty.