3.0 KiB
Schema strategy (dev) and persistence switching
Goal
Keep the core domain independent from persistence details, while still providing a fast dev loop. Persistence and schema behavior are configured at the application boundary (the API app), not inside the domain.
Persistence modes (API runtime)
The API supports two persistence modes, controlled by ProcessEnv.GRIDPILOT_API_PERSISTENCE:
inmemory: no database required; the API runs with in-memory adapters.postgres: the API uses Postgres via TypeORM.
Default inference (dev ergonomics)
If GRIDPILOT_API_PERSISTENCE is unset, the API infers persistence from DATABASE_URL via getApiPersistence():
- If
DATABASE_URLis set →postgres - Otherwise →
inmemory
This is why dev compose should not hard-code GRIDPILOT_API_PERSISTENCE; it should allow inference unless explicitly overridden.
Schema strategy in development (TypeORM synchronize)
When the API runs in Postgres mode, it loads DatabaseModule, which configures TypeORM with:
synchronize: process.env.NODE_ENV !== 'production'inTypeOrmModule.forRoot()
Practical meaning:
- Development/test: TypeORM
synchronizeis enabled to keep schema aligned automatically during iteration. - Production: TypeORM
synchronizeis disabled.
Migrations (deferred)
Migrations are intentionally deferred for now: local dev relies on synchronize for speed, while production-grade migrations will be introduced later at the infrastructure boundary (without changing the domain).
Switching modes locally
Docker dev (recommended)
In docker-compose.dev.yml, GRIDPILOT_API_PERSISTENCE should be optional so the default inference works.
To force a mode, set one of:
GRIDPILOT_API_PERSISTENCE=inmemoryGRIDPILOT_API_PERSISTENCE=postgres
Example environment reference (dev): DATABASE_URL and optional persistence override (commented) in .env.development.example.
Dev seeding behavior (high level)
Seeding/bootstrap runs at API startup via BootstrapModule, unless disabled with GRIDPILOT_API_BOOTSTRAP=0 (parsed by getEnableBootstrap()).
At startup:
- Always runs
EnsureInitialData.execute()inBootstrapModule.onModuleInit(). - Seeds racing data via
SeedRacingDatawhen:- persistence is
inmemory, or - persistence is
postgresANDNODE_ENV !== 'production'AND the racing DB appears empty (checked via the league repository) inBootstrapModule.shouldSeedRacingData().
- persistence is
This keeps dev environments usable without requiring manual seed steps, while avoiding unexpected reseeding in production.