Migration Usage
Environment setup
The migration package reads its database credentials from migration/.env. Two variables are required:
# Connection string for Azure Cosmos DB for MongoDB API (source, read-only)
MONGO_SOURCE_URL=mongodb+srv://...
# Prisma connection string for the target PostgreSQL database
DATABASE_URL=postgresql://...MONGO_SOURCE_URL must point to an account or user that has at minimum read access to the collections listed in Phase 1. The migrator opens the connection with ReadPreference.SECONDARY_PREFERRED to avoid load on the primary. DATABASE_URL should point to the target environment you intend to populate (typically the dev or staging database — never the live v3 production database during initial migration testing).
Do not commit migration/.env. It is excluded from version control.
Run commands
All commands are defined in migration/package.json and run via pnpm workspace filter.
Live run
pnpm --filter @leadmetrics/migration migrateRuns all enabled steps in order, writes to PostgreSQL. Use this for the actual migration.
Dry run
pnpm --filter @leadmetrics/migration migrate:dryRuns all enabled steps but skips every database write (both write() and relatedWriter calls). Useful for verifying mapping logic, checking for null returns from mapDoc, and reviewing progress output without touching the target database.
Important dry-run limitation: The subscription step builds its plan lookup from the plan table, which is populated by the offering step. In a dry run, the offering step skips its writes, so the plan table remains empty. As a result, the subscription step’s setup() will load zero plans, and all 286 subscription documents will be skipped due to unresolvable plan keys. This is expected behaviour in dry-run mode — it does not indicate a mapping bug.
Run specific steps
pnpm --filter @leadmetrics/migration migrate -- --only offering,tenantRuns only the named steps (comma-separated keys matching the key field in migration.config.ts). All other steps are skipped regardless of their enabled flag. Useful for re-running a single step after fixing source data or adjusting a map file.
Combine flags
pnpm --filter @leadmetrics/migration migrate -- --only subscription --dry-run--dry-run and --only can be combined. This example runs only the subscription step in dry-run mode.
Re-running is safe
Every write in the migration uses either createMany({ skipDuplicates: true }) or upsert. If you re-run a step after it has already written data, existing rows are silently ignored and no duplicates are created. This means you can safely re-run the full migration or any individual step after fixing a map file or source data issue.
Adding a new step
- Create a new map file in
config/maps/following the naming convention (07-foo.map.ts). See map-files.md for the annotated template. - Open
config/migration.config.tsand add an entry to thestepsarray:
{
key: "foo",
mapFile: "07-foo.map.ts",
enabled: true,
}- Set
enabled: falseif the step is not ready to run. Disabled steps are printed in the summary as “SKIPPED” but do not cause errors. - Run
migrate:dryto validate the new step before a live run.