0140 — File units, leases, tours and renewal rows by company, on the existing phone-index

Context

The staff "All companies" Leasing numbers fold each company separately. Each company leg reads every building one at a time: about 8.5 database calls per building, 598 for the 70-building company on stage, 513 per cold request on prod (p75 2.5 s). Prospects and occupancies already have company partitions. Units, leases, tours and renewal rows do not.

Stage, measured read-only on 2026-09-29: for each of the two 70-building companies, all four row types together come to under 1 MB, each type fitting in a single query page (largest: leases, 188 rows, 165 KB). A company read is therefore one query per row type, not a sequential drain.

Design A proposed a new index. The table has 19 of 20 indexes on prod. The one prod lacks from stage, conv-nontest-recency-index (ADR-0138), is owed the 20th slot.

Decision

No new index. The keys ride the existing phone-index (HASH GSI1PK, RANGE GSI1SK, projection ALL, present on both tables):

GSI1PK ORGROW#<organizationId>#<entity>, entity one of unit, lease, tour, renewal
GSI1SK <propertyId>#<rowId>

Rollout

  1. Keys stamped by the writers, one row type per PR, plus the reader function, unused.
  2. Backfill (dry-run by default, ledger), prefix-guarded revert, parity with a NO-GO gate.
  3. Stage backfill and parity; stage timing. Production dry-run counts go to Gera. The production apply is Gera's act.
  4. The Leasing fold reads by company only after part 4c (consistent building read, keep-on-failure) is merged AND on a fresh production parity GO. Parity is a read-only check that can be re-run at any time, not a one-time gate: it is re-run right before part 5 merges, and again after any backfill, revert or building move. A GO from an earlier day does not count.

Consequences