Files
nick-doc/PRD - Mongo Retirement (Full Nuke).md

11 KiB
Raw Permalink Blame History

PRD — Mongo Retirement: Full Code Nuke

Status: In Progress
Date: 2026-06-06
Scope: Remove every Mongoose/MongoDB reference from the codebase and replace Mongo-style ObjectId fields with plain UUID strings throughout.


Context

The Mongo→Postgres migration scaffolding is complete:

  • 25 Drizzle schemas cover all 23 collections
  • 11 Drizzle repos, 11 Mongo repos, 9 DualWrite fan-out repos
  • Backfill scripts written (not yet run against production)
  • Factory defaults to mongo; reads not yet cut over
  • Chat uses a JSONB shim (acceptable for now — normalize later)

This PRD covers the code-level retirement: delete all Mongoose artifacts, flip the factory to Postgres-only, remove MongoDB from docker-compose and package.json, and replace Types.ObjectId with string (UUID) across every interface and schema.

Production data migration (backfill execution + read-cutover per domain) is a separate, human-gated operation and is NOT in scope here.


Goals

  1. Zero mongoose or mongodb imports anywhere in backend/
  2. Zero Schema.Types.ObjectId / Types.ObjectId field types
  3. Zero _id: ObjectId interface declarations (replaced with id: string)
  4. Zero ObjectId(...) constructors or .toString() coercions on IDs
  5. MongoDB service removed from all docker-compose files
  6. mongoose removed from package.json
  7. MONGODB_URI / MONGO_* env vars removed from config and docs
  8. Factory defaults to pg; Mongo and DualWrite modes deleted
  9. Seeds and scripts updated to target Postgres only
  10. Frontend: legacy ObjectId validation path removed

Out of Scope

  • Backfill execution against production data
  • Production env var changes (REPO_*, MONGO_CONNECT_MODE)
  • Chat normalization (JSONB → child tables) — tracked separately
  • Drizzle schema changes (schemas are already correct)
  • Any Drizzle repo logic changes

Phased Work Plan

Phase 1 — Factory Cutover & Repo Deletion (Day 1)

1.1 Factory: delete Mongo + DualWrite modes

  • File: src/db/repositories/factory.ts
  • Change: remove all mongo and dual branches; every domain returns its Drizzle repo directly
  • Remove REPO_* env flag checks (no longer needed)
  • Remove all imports of Mongo repos and DualWrite repos

1.2 Delete Mongo repo files (11 files)

src/db/repositories/mongo/MongoUserRepo.ts
src/db/repositories/mongo/MongoPaymentRepo.ts
src/db/repositories/mongo/MongoPointsRepo.ts
src/db/repositories/mongo/MongoMarketplaceRepo.ts
src/db/repositories/mongo/MongoBlogRepo.ts
src/db/repositories/mongo/MongoNotificationRepo.ts
src/db/repositories/mongo/MongoDisputeRepo.ts
src/db/repositories/mongo/MongoTrezorAccountRepo.ts
src/db/repositories/mongo/MongoDerivedDestinationRepo.ts
src/db/repositories/mongo/MongoChatRepo.ts
src/db/repositories/mongo/MongoReleaseHoldRepo.ts
src/db/repositories/mongo/index.ts

1.3 Delete DualWrite repo files (9 files)

src/db/repositories/dual/DualWriteUserRepo.ts
src/db/repositories/dual/DualWritePaymentRepo.ts
src/db/repositories/dual/DualWritePointsRepo.ts
src/db/repositories/dual/DualWriteMarketplaceRepo.ts
src/db/repositories/dual/DualWriteBlogRepo.ts
src/db/repositories/dual/DualWriteNotificationRepo.ts
src/db/repositories/dual/DualWriteDisputeRepo.ts
src/db/repositories/dual/DualWriteTrezorAccountRepo.ts
src/db/repositories/dual/DualWriteDerivedDestinationRepo.ts
src/db/repositories/dual/index.ts

Phase 2 — Mongoose Model Deletion & Interface Extraction (Day 12)

2.1 Extract pure TS interfaces from each model file

For each of the 24 model files in src/models/, the plan is:

  • Keep the I<Name> TypeScript interface (with id: string replacing _id: Types.ObjectId)
  • Delete the new Schema(...) definition, virtual fields, pre/post hooks
  • Delete the mongoose.model<I<Name>>(...) export
  • Delete the mongoose import

The interface files move to src/types/models/ (or inline into the Drizzle schema files as inferred types).

2.2 Convert all _idid: string in interfaces

Key changes per domain:

  • IUser._id: Types.ObjectIdid: string
  • ICategory._idid: string, parentId: string | null
  • IPurchaseRequest._idid: string, buyerId/sellerId: string
  • ISellerOffer._idid: string, sellerId/purchaseRequestId: string
  • IPayment._idid: string, polymorphic fields → string
  • IChat._idid: string, senderId/userId: string
  • IDispute._idid: string, all ref fields → string
  • All others follow same pattern

2.3 Delete src/models/ directory after interfaces extracted


Phase 3 — Mongoose Connection & Config Removal (Day 2)

3.1 src/infrastructure/database/connection.ts

  • Remove mongoose.connect() call and all Mongo connection logic
  • Remove MONGO_CONNECT_MODE handling
  • Keep only the Postgres pool initialization

3.2 src/shared/config/index.ts

  • Remove mongoUri field
  • Remove MONGODB_URI env var read

3.3 src/services/auth/authStore.ts

  • Remove AUTH_FALLBACK_MONGO, AUTH_MIRROR_MONGO, MONGO_CONNECT_MODE branches
  • Auth reads only from Postgres

3.4 src/services/health/healthCheckService.ts

  • Remove MongoDB health check
  • Remove MONGO_CONNECT_MODE reference

3.5 src/app.ts

  • Remove mongoose.connect() / connectMongo() call on startup
  • Remove p.userId.toString() ObjectId coercions (already string)

Phase 4 — Seeds & Scripts Cleanup (Day 2)

4.1 Seeds (src/seeds/)

  • Remove mongoose.connect() from all 7 seed files
  • Seeds already have PG-aware paths; remove Mongo dual-path
  • seedUsers.ts, seedLevels.ts, seedCategories.ts, etc.

4.2 Scripts (src/scripts/)

  • Remove Mongoose imports from 13 scripts
  • Scripts that only operated on Mongo (e.g. clearChats.ts, updateRequestStatus.ts) — convert to Postgres queries or delete if obsolete

Phase 5 — Backfill Infrastructure (Day 3)

5.1 Archive backfill scripts (don't delete — needed for production data migration)

  • Move src/db/backfill/src/db/backfill/_archive/
  • OR keep as-is but add a .nocompile flag / remove from tsconfig paths
  • The backfill scripts import mongoose (to read from Mongo) — they're tools for ops, not app code

5.2 Remove verification layer Mongo references

  • src/db/verify/shadowRead.ts — remove Mongo comparison path
  • src/db/verify/rowCounts.ts — remove Mongo row count queries
  • src/db/verify/checksums.ts — remove Mongo checksum queries
  • src/db/verify/reconcile.ts — keep (handles pg_dualwrite_gaps replay, still useful)

5.3 _idMap.ts — keep as a utility for ops scripts only; remove from app imports


Phase 6 — Docker & Dependencies (Day 3)

6.1 docker-compose.dev.yml

  • Remove mongodb service block
  • Remove depends_on: mongodb from backend service
  • Remove all *_STORE=mongo env vars (Auth, Config, Address, etc.)
  • Remove mongodb_data volume

6.2 docker-compose.production.yml

  • Same: remove mongodb service, depends_on, volume

6.3 deployment/docker-compose.yml

  • Same: remove mongodb service block

6.4 backend/package.json

  • Remove mongoose from dependencies
  • Remove mongodb-memory-server from devDependencies

6.5 .env.example / .env.development / .env.local

  • Remove MONGODB_URI, MONGO_CONNECT_MODE, AUTH_FALLBACK_MONGO, AUTH_MIRROR_MONGO
  • Remove MONGO_INITDB_* vars

Phase 7 — Frontend ID Validation Cleanup (Day 3)

7.1 Remove ObjectId validation branch

  • frontend/src/sections/request-template/view/seller-shop-view.tsx:78
  • Remove the "legacy 24-hex Mongo ObjectId" validation path
  • Keep only UUID validation

7.2 Audit frontend for other ObjectId references

  • grep -r 'ObjectId\|[0-9a-f]{24}' frontend/src/
  • Remove any other legacy ID format handling

Phase 8 — TypeScript Compilation Check (Day 3)

  • npm run tsc — fix all remaining type errors from the migration
  • Common issues: .toString() on already-string IDs, _id vs id mismatches, missing UUID imports

Files to Delete (Complete List)

Mongoose Model Files (24)

backend/src/models/User.ts
backend/src/models/Category.ts
backend/src/models/PurchaseRequest.ts
backend/src/models/SellerOffer.ts
backend/src/models/Payment.ts
backend/src/models/Chat.ts
backend/src/models/Dispute.ts
backend/src/models/Review.ts
backend/src/models/Address.ts
backend/src/models/Notification.ts
backend/src/models/TelegramLink.ts
backend/src/models/TelegramSession.ts
backend/src/models/TempVerification.ts
backend/src/models/TrezorAccount.ts
backend/src/models/DerivedDestination.ts
backend/src/models/FundsLedgerEntry.ts
backend/src/models/PointTransaction.ts
backend/src/models/RequestTemplate.ts
backend/src/models/BlogPost.ts
backend/src/models/ConfigSetting.ts
backend/src/models/ConfigSettingHistory.ts
backend/src/models/LevelConfig.ts
backend/src/models/ShopSettings.ts
backend/src/models/index.ts

Mongo Repos (11+index)

backend/src/db/repositories/mongo/ (entire directory)

DualWrite Repos (9+index)

backend/src/db/repositories/dual/ (entire directory)

ID Migration Pattern

Every interface field that was Types.ObjectId or Schema.Types.ObjectId becomes string (UUID).

Before:

interface ISellerOffer {
  _id: Types.ObjectId;
  sellerId: Types.ObjectId | string;
  purchaseRequestId: Types.ObjectId | string;
}

After:

interface ISellerOffer {
  id: string;  // UUID
  sellerId: string;
  purchaseRequestId: string;
}

Any code doing someDoc._id.toString()someDoc.id (already a string). Any code doing new mongoose.Types.ObjectId(value) → just use value as string.


Risk Register

Risk Mitigation
App breaks because Mongo isn't seeded in dev Run npm run seed:pg before removing Mongo from docker-compose
Type errors cascade from _idid rename Fix systematically: models first, then services/routes
Backfill scripts break (they import mongoose) Keep backfill dir outside tsconfig compilation scope
Auth fallback to Mongo breaks login Auth already has PG path; remove fallback gate
Chat reads fail (JSONB shim) JSONB shim already works; normalization is future work

Acceptance Criteria

  • grep -r "mongoose" backend/src/ --include="*.ts" returns zero hits (excluding backfill archive)
  • grep -r "Types.ObjectId\|Schema.Types.ObjectId" backend/src/ returns zero hits
  • grep -r "mongodb" backend/package.json returns zero hits
  • grep -r "MONGODB_URI\|MONGO_CONNECT_MODE" backend/src/ returns zero hits
  • npm run tsc exits 0
  • Backend starts with MONGO_CONNECT_MODE=never (or removed) and REPO_*=pg (or removed)
  • Seed scripts populate Postgres successfully
  • All docker-compose files have no mongodb service