Skip to content

Backups & Migrations

Gatewyse ships two operational tools for protecting and evolving your data: an S3-backed backup and restore system, and a reversible schema migration runner.

Backups & Restore

Backups run as BullMQ jobs on the log-backup queue: the worker runs mongodump, uploads the archive to S3, and writes a sha256 checksum sidecar alongside it. Backups are limited to an allow-listed set of collections — audit_logs, request_logs, usage_records, documents, document_chunks — to prevent exfiltration of sensitive collections such as users or API keys.

Triggering a backup

POST /api/admin/backups
Content-Type: application/json
{ "collections": ["audit_logs", "request_logs"] }
  • Super-admin only. Backups can contain cross-tenant data, so the route rejects anyone without the super-admin role (in addition to the backups:create permission).
  • Requested collections are filtered against the allow-list; omitting collections backs up the full allowed set.
  • A user-supplied s3Bucket is ignored for security — the configured default destination is always used.
  • Returns 202 Accepted with a jobId. Poll GET /api/admin/backups/:jobId for status, or GET /api/admin/backups to list recent jobs.

Restoring a backup

POST /api/admin/backups/:jobId/restore
Content-Type: application/json
{ "drop": false }
  • Super-admin only (same guard as backup).
  • The source backup must be in the completed state and have an uploaded S3 archive; otherwise the request is rejected.
  • The worker downloads the archive from S3 and verifies its sha256 checksum sidecar before replaying via mongorestore, aborting on any mismatch — a corrupted or tampered archive is never restored.
  • "drop": true passes --drop to mongorestore, replacing the target collections (destructive). Leave it false to merge. Test destructive restores into a scratch database first.
  • Returns 202 Accepted with a restore jobId; poll GET /api/admin/backups/:jobId for progress.

Recovery objectives

RTO and RPO are deployment-specific:

  • RPO (data-loss window) is the age of the most recent successful backup. Backups here are on-demand plus a scheduled log-backup cron — set the cron cadence to your tolerable RPO (e.g. hourly ⇒ ≤ 1h RPO).
  • RTO (time-to-restore) is archive download plus mongorestore time, roughly linear in dataset size.

Schema Migrations

Schema migrations are applied with the migration runner. Each applied migration is recorded in a schema_migrations collection, so the runner knows what has already run and migrations are never applied twice.

Run it via the server package script:

Terminal window
pnpm --filter @ai-gateway/server migrate <command>

which invokes tsx src/scripts/migrate.ts. The available subcommands are:

CommandEffect
upApply all pending migrations. Reports how many ran (or “Already up to date”).
downRevert the single most recently applied migration.
statusShow every migration with its id, name, and whether it has been applied (and when). This is the default when no subcommand is given.
Terminal window
# Show applied / pending migrations
pnpm --filter @ai-gateway/server migrate status
# Apply all pending migrations
pnpm --filter @ai-gateway/server migrate up
# Revert the most recent migration
pnpm --filter @ai-gateway/server migrate down

An unknown subcommand exits non-zero with a usage message (Use up | down | status.). Run status before and after up/down to confirm the applied set.