Overview
Project Zoe uses PostgreSQL with TypeORM. Schema management differs by environment:
Never set DB_SYNCHRONIZE=true in staging or production. It can silently drop columns or tables. All staging and production schema changes must go through a migration file.
Running migrations
Creating a migration
After modifying a TypeORM entity, generate a migration automatically:
TypeORM diffs the current database schema against the entity definitions and writes a migration file with up() and down() methods.
Always review the generated file before committing — TypeORM occasionally generates destructive statements (e.g. dropping a column it thinks was removed) that need to be corrected manually.
Migration workflow
- Make your entity change.
- Generate the migration:
npm run migration:generate -- src/migrations/<Name>.
- Review the generated file in
src/migrations/.
- Test locally:
npm run migration:run then npm run migration:revert to confirm both directions work.
- Commit the entity change and the migration file together in the same PR.
CI applies pending migrations (npm run migration:run) on every deploy to staging and production before restarting the app.
Migration files location
Multi-tenancy indexing
All major entities have composite indexes on (tenant, id) and other frequently-queried columns:
This ensures queries are always scoped efficiently to a single tenant and never scan the full table.
Data source
The TypeORM DataSource is configured in src/data-source.ts and used by both the app and the migration CLI:
Seeding
Demo data is seeded via NestJS commands (not migrations) so seeding can be run independently of schema management:
See the Quickstart for a full seeding walkthrough.