Backups and migrations
Data layout
- Postgres
publicschema: platform data (tenant registry, accounts, memberships, licenses, superadmins, sessions).- One schema per tenant:
tenant_<identifier>, holding all of that organisation's data. Each request runs withsearch_pathset to the tenant's schema.
- S3 bucket (
S3_BUCKET): uploaded files, undertenant/<tenantId>/documents/<documentId>/versions/<versionId><ext>, each tagged with the tenant ID.
Back up both. Documents in the database refer to objects in the bucket.
Backups
# Database (all schemas)
docker compose exec -T postgres pg_dump -U orbit -Fc orbit > orbit-$(date +%F).dump
# Files (any S3 client), for example:
aws --endpoint-url http://localhost:8334 s3 sync s3://orbit-storage ./orbit-files-$(date +%F)
Restore:
docker compose exec -T postgres pg_restore -U orbit -d orbit --clean < orbit-YYYY-MM-DD.dump
aws --endpoint-url http://localhost:8334 s3 sync ./orbit-files-YYYY-MM-DD s3://orbit-storage
One tenant only: pg_dump -n tenant_<identifier>. You also need its rows in public (registry, memberships) to restore it on another platform.
Test restores regularly on a non-production stack.
Migrations
pnpm migrate # public + every tenant schema
- The API and worker also migrate at start-up, so a deploy migrates automatically.
- Each schema records the migrations it has applied in its own
_orbitMigrationstable, so new tenants and old ones converge. - System definition sets are ensured in every tenant on each migration.
- Developers generate migrations with
pnpm db:generateafter changingpackages/db/src/schema.
Upgrading
- Back up the database and bucket.
- Pull the new version, then
docker compose up -d --build. - Watch the API log for migration output; check
/v1/statusand sign in.