Database backup & cross-dialect migration in Node.js — one source, many destinations, with @mostajs/orm-copy-data

Database backup & cross-dialect migration in Node.js — one source, many destinations, with @mostajs/orm-copy-data

Part of the @mostajs/orm ecosystem — the multi-dialect ORM with one API across 13 databases. This post zooms in on one-shot data copy: backup, migration, seeding.

TL;DR

@mostajs/orm-copy-data copies data fan-out: read one source (a database, or a CSV / JSON / SQL file) and write it to N heterogeneous destinations — another database, a SQL dump, JSON, CSV — in a single operation.

npm i @mostajs/orm-copy-data

One-shot, not continuous (and why that matters)

The @mostajs ecosystem has two replication-adjacent tools, and they don’t overlap:

If you want “keep these two databases in sync forever”, that’s the replicator. If you want “take prod and put it there, now (and maybe also dump it to a file)”, that’s this package.

The fan-out idea

Most backup scripts target one output. Here, destinations is an array — the same read pass feeds every target. One nightly job can produce a hot standby database and a portable SQL dump and a JSON archive, without reading the source three times:

mostajs-copy \
  --source db --source-dialect postgres --source-uri "$PROD_URI" \
  --dest db       --dest-dialect sqlite --dest-uri "./backups/$(date +%Y%m%d).sqlite" \
  --dest sql-dump --dest-file "./backups/$(date +%Y%m%d).sql" \
  --dest json     --dest-file "./backups/$(date +%Y%m%d).json" \
  --schemas entities.json --create-tables --batch-size 1000

Four formats out of one source, one command. --dest is repeatable; --create-tables provisions empty database targets; --batch-size (default 500) bounds memory on big tables.

Every direction works

Sources and destinations are symmetric — db | csv | json | sql in, db | csv | json | sql-dump out — so the same binary covers the whole lifecycle:

# Cross-dialect migration : Postgres → SQLite (one shot)
mostajs-copy --source db --source-dialect postgres --source-uri "$PROD" \
             --dest db --dest-dialect sqlite --dest-uri ./local.sqlite \
             --schemas entities.json --create-tables

# Restore : SQL dump → a fresh database
mostajs-copy --source sql --source-file ./backup.sql \
             --dest db --dest-dialect sqlite --dest-uri ./restored.sqlite \
             --schemas entities.json --create-tables

# Seed dev : JSON → SQLite
mostajs-copy --source json --source-file ./seed.json \
             --dest db --dest-dialect sqlite --dest-uri ./dev.sqlite --create-tables

# Export for BI : Postgres → CSV (one file per entity)
mostajs-copy --source db --source-dialect postgres --source-uri "$PROD" \
             --dest csv --dest-file ./export/ --schemas entities.json

Need a subset? --entities User,Product,Order filters which entities are copied (default: all).

Repeatable jobs — --commandFile + cron

For anything you run more than once, move the flags into a file (one flag per line, # comments, quoted values):

# backup-daily.conf  —  Postgres → SQLite + SQL dump + JSON
--source db
--source-dialect postgres
--source-uri "postgresql://user:pass@localhost:5432/prod"
--dest db        --dest-dialect sqlite --dest-uri "./backups/daily.sqlite"
--dest sql-dump  --dest-file "./backups/daily.sql"
--dest json      --dest-file "./backups/daily.json"
--schemas .mostajs/generated/entities.json
--create-tables
--batch-size 1000
# /etc/cron.d/mostajs-backup
0 2 * * * cd /app && npx mostajs-copy --commandFile backup-daily.conf >> /var/log/backup.log 2>&1

Extra CLI flags override or extend the file, so one base config covers many variants.

Or drive it from code

The API is one call — copyData({ source, destinations, schemas, options }) — returning a CopyResult with per-entity stats:

import { copyData } from '@mostajs/orm-copy-data'
import { UserSchema, OrderSchema } from './schemas'

const result = await copyData({
  source:       { type: 'db', dialect: 'mongodb', uri: process.env.MONGO_URL },
  destinations: [
    { type: 'db',       dialect: 'postgres', uri: process.env.PG_URL, createTables: true },
    { type: 'sql-dump', file: './backup/dump.sql' },
    { type: 'json',     file: './backup/data.json' },
  ],
  schemas: [UserSchema, OrderSchema],
  options: { batchSize: 500, onProgress: (e, c, t) => console.log(`${e}: ${c}/${t}`) },
})
console.log(result.totalCopied, result.totalErrors)

That example is the headline trick in code: MongoDB → Postgres + SQL dump + JSON, in one pass. The individual loadFromDb/Json/Csv/Sql and writeToDb/Sql/Json/Csv building blocks are exported too, if you want to compose your own pipeline.

Use cases at a glance

Use case How
Daily backup mostajs-copy --commandFile backup.conf via cron
Cross-dialect migration Oracle → PostgreSQL, one shot
Dev seeding JSON → SQLite for local dev
Export for analytics Postgres → CSV for BI tools
Disaster recovery SQL dump → new database
Data archiving Prod DB → JSON/CSV

Honest notes

Where it fits

Because it reads and writes through @mostajs/orm EntitySchema, the entities you back up or migrate are the same ones your app runs on — one model end to end. Its continuous counterpart is @mostajs/replicator; the @mostajs/orm-cli uses this engine internally for its Prisma-bootstrap migration.

Get started

npm i @mostajs/orm-copy-data        # + the driver(s) for your source AND destination dialects
mostajs-copy --help

If “back up and migrate any of 13 databases with one command” is useful, a ⭐ on GitHub helps — it’s the signal AI dev tools use to surface the package.

Tags: #nodejs #typescript #database #backup #migration #postgresql #mongodb #sqlite #csv #json #etl #orm #mostajs

Auteur : Dr Hamid MADANI drmdh@msn.com