--- title: Postgres Runtime Cutover Status tags: [data-model, postgres, migration, runtime-status] aliases: [Postgres Status, PG Cutover Status, Mongo vs Postgres Runtime] created: 2026-05-31 source: backend origin/integrate-main-into-development@cab0719 --- # Postgres Runtime Cutover Status > **Current branch:** backend `origin/integrate-main-into-development` at `cab0719`, version `2.6.80`. > > **Bottom line:** this branch is **Postgres-capable**, not fully Postgres-backed. MongoDB remains the live source of truth for normal app traffic until services are actually rewired through the repository factory and cutover flags are verified in a running environment. ## What Uses Postgres Now | Area | Runtime status | Notes | |---|---|---| | Postgres connection | Available when `PG_URL` is set | `src/db/client.ts` fail-fast requires an explicit DSN before importing PG code. | | Schema/migrations | Implemented through migration `0008` | Drizzle schemas cover users, categories, purchase requests, seller offers, payments, funds ledger, derived destinations, trezor accounts, points, `id_map`, `pg_dualwrite_gaps`, and `payment_quotes`. | | Repository implementations | Implemented but not broadly called | `src/db/repositories/{mongo,drizzle,dual}` and `factory.ts` exist for user, payment, points, and marketplace domains. | | Oracle quote persistence | Conditional runtime PG write | `/api/payment/request-network/intents` lazily imports `quoteRepo` only when `ORACLE_QUOTING_ENABLED=true`; it writes `payment_quotes` if the PG parent payment row exists, mirrors to Mongo `Payment.quote`, and records `pg_dualwrite_gaps` if PG is behind. | | Backfill/verify scripts | Available as operator tooling | `MIGRATION_PG_URL` drives backfill scripts; guards restrict allowed target hosts. These scripts are not run automatically by app startup. | ## What Is Still Mongo-Backed The service layer still imports Mongoose models directly. A source scan on 2026-05-31 found no runtime calls to `createRepositories()` / `getPaymentRepo()` / `getMarketplaceRepo()` outside `src/db/repositories/factory.ts`; the only normal service import of `src/db/client.ts` is `priceOracle/quoteRepo.ts`. | Domain | Current live store | Why not Postgres yet | |---|---|---| | Auth, users, passkeys, refresh tokens | MongoDB | Auth/user controllers call `User` and related Mongoose models directly. | | Marketplace requests/offers/templates/categories/shop settings | MongoDB | Marketplace, checkout, and seller-offer services call `PurchaseRequest`, `SellerOffer`, `RequestTemplate`, `Category`, and `ShopSettings` directly. | | Payments and escrow state | MongoDB primary | Request Network, AMN scanner, webhook, admin, release/refund, adapter, reconciliation, and legacy payment paths still create/update `Payment` Mongoose documents directly. | | Funds ledger | MongoDB primary | `FundsLedgerEntry` remains the ledger used by current services; PG ledger tables exist but are not the live write target. | | Derived destinations and sweeps | MongoDB | Wallet destination allocation and sweep services call `DerivedDestination` directly. | | Points/referrals/levels | MongoDB | Points service uses `User`, `PointTransaction`, `LevelConfig`, and Mongo transactions. | | Chat/messages | MongoDB | Chat intentionally remains document-shaped and is not part of the current PG cutover. | | Notifications | MongoDB | Notification TTL/read-state paths remain Mongo-backed. | | Disputes/reviews/blog/content/admin cleanup | MongoDB | These services still call their Mongoose models directly. | | Runtime config | MongoDB | `ConfigSetting` and `ConfigSettingHistory` remain Mongo-backed for admin-editable configuration. | | Telegram link/session/temp verification | MongoDB | These session/link/TTL records are not cut over to PG. | ## Env Flag Reality | Flag | Current meaning | |---|---| | `PG_URL` | Makes PG code importable/reachable; does not cut over app domains by itself. | | `MIGRATION_PG_URL` | Used by backfill scripts and migration runbooks; not part of normal request handling. | | `REPO_USER`, `REPO_PAYMENT`, `REPO_POINTS`, `REPO_MARKETPLACE`, `REPO_DEFAULT` | Repository factory flags exist, but broad services are not yet wired through the factory. Treat them as migration controls that need integration verification before relying on them. | | `ORACLE_QUOTING_ENABLED` | Enables server-side quote computation and the only current PG write path in normal checkout: `payment_quotes`, when a PG parent row can be resolved. | ## Next Cutover Work 1. Apply Drizzle migrations to the target Postgres database. 2. Run non-prod backfills in dependency order and record row-count/checksum results. 3. Wire services to repository interfaces one domain at a time. 4. Enable `dual` mode per domain only after wiring is proven by tests and smoke checks. 5. Run shadow-read/reconcile during a soak window. 6. Flip reads to `pg` per domain only after zero-diff shadow reads and a rollback plan are in place. ## Related Docs - [[Database Strategy - Mongo vs Postgres Assessment]] - [[MongoDB to PostgreSQL Migration Plan (Drizzle)]] - [[Payment]] - [[Payment API]] - [[Environment Variables]] - [[Database Operations]]