Skip to main content

Backend evolution: Mongo → Postgres

The single most important thing to understand about Drape's architecture right now is that there are two backend generations running in parallel, and the platform is mid-migration between them.

Generation 2 — Postgres backend (develop / staging)

Generation 1 — MongoDB monolith (main)

one-way data migration

backend/server.py
~8,900-line FastAPI monolith
motor / pymongo

backend-postgres/
modular FastAPI + helpers/
asyncpg · 30 SQL migrations

Mobile app
Drape- / frontend

Web tier
marketing · brand · admin

Where each lives

Generation 1 (Mongo)Generation 2 (Postgres)
Branchmaindevelop, staging
Codebackend/server.py (one ~8,900-line file)backend-postgres/ (modular)
DatastoreMongoDB (motor/pymongo)PostgreSQL (asyncpg, DATABASE_URL)
DeployRender — drape-backend-avjg.onrender.comECS Fargate on cluster drapeapi.drape.to (prod) / dev-api.drape.to (dev)
ConsumersThe Expo mobile appThe marketing, brand, and admin web surfaces
SchemaImplicit (documents)Explicit — 30 ordered database/migrations/*.sql

What the Postgres backend adds

backend-postgres/ is not a like-for-like port — it is a re-architecture. It is modular where the monolith is one file (server.py + config.py + clients.py

  • dependencies.py + database/connection.py + a helpers/ package), and it carries features the Mongo backend never had:
  • RBAC brand teams — roles, invites, permissions (helpers/brand_roles.py, brand_team_invites.py, brand_permissions.py; migrations 018, 021).
  • Brand integrations & webhooks (helpers/brand_webhooks.py, integrations_catalog.py; migration 023).
  • Live streaming via Mux (helpers/mux_live.py).
  • Explore / social with realtime and comment moderation (helpers/explore_realtime.py; migrations 024, 029, 030).
  • In-store payments and store locations (migrations 020, 022).
  • Admin email campaigns — templates, bulk send, inbound mailbox (helpers/admin_email.py, admin_inbound.py; migrations 016, 017).
  • Engagement — drops v2, stock waitlists, price alerts (helpers/price_alerts.py; migrations 026–028).
  • Order fulfillment and plan enforcement (helpers/order_fulfillment.py, plan_enforcement.py; migrations 008, 009).

The ordered migration series (004 → 030) is effectively the changelog of the Postgres backend's feature build-out.

The data migration

backend/scripts/migrate_mongo_to_postgres.py (on develop/staging) is the one-way data mover: it opens both a motor MongoDB client and an asyncpg Postgres pool and copies collections (stores, users, products, orders, …) from the fitpreview_db Mongo database into the Postgres schema.

DATABASE_URL=<postgres-url> MONGO_URL=<mongo-url> DB_NAME=fitpreview_db \
python backend/scripts/migrate_mongo_to_postgres.py

The honest status

Two generations, one in-flight cut-over

The web tier is already live on the Postgres backend (brand.drape.to accepts applications and logins today). The mobile app is still on the MongoDB monolith in production (drape-backend-avjg.onrender.com). Postgres code lives in backend-postgres/ on Drape-AI-LLC/Drape-; develop auto-deploys ECS drape-dev, and prod is workflow_dispatch to ECS drape-prod.

This means Drape is running two backend generations at once, on two hosts: Render (Mongo) and AWS ECS/RDS (Postgres). Before treating any single backend as canonical, verify which host a surface calls. The rest of the architecture section documents the MongoDB backend (the one the shipped mobile app depends on) as the baseline, and flags Postgres-only capabilities where they matter.

Why this is the right frame

For a solo-founder platform, standing up the newer, richer capabilities (marketplace teams, integrations, live, social) on a relational schema while keeping the proven Mongo backend serving the shipped app is a pragmatic strangler-fig migration — the web tier leads, the mobile app follows once the Postgres backend reaches parity on the try-on path. The risk to manage is exactly the one above: clarity about which backend owns which surface at any moment. See System overview for how this maps across surfaces, Infrastructure for hosts, and Backend (MongoDB) for the generation the mobile app runs on.