# 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`](apps/api/src/env.d.ts:7):

- **`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()`](apps/api/src/env.ts:33):

- If `DATABASE_URL` is 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`](apps/api/src/domain/database/DatabaseModule.ts:1), which configures TypeORM with:

- `synchronize: process.env.NODE_ENV !== 'production'` in [`TypeOrmModule.forRoot()`](apps/api/src/domain/database/DatabaseModule.ts:6)

Practical meaning:
- **Development/test:** TypeORM `synchronize` is enabled to keep schema aligned automatically during iteration.
- **Production:** TypeORM `synchronize` is 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`](docker-compose.dev.yml:1), `GRIDPILOT_API_PERSISTENCE` should be optional so the default inference works.

To force a mode, set one of:
- `GRIDPILOT_API_PERSISTENCE=inmemory`
- `GRIDPILOT_API_PERSISTENCE=postgres`

Example environment reference (dev): [`DATABASE_URL`](.env.development.example:20) and optional persistence override (commented) in [`.env.development.example`](.env.development.example:17).

## Dev seeding behavior (high level)
Seeding/bootstrap runs at API startup via [`BootstrapModule`](apps/api/src/domain/bootstrap/BootstrapModule.ts:1), unless disabled with `GRIDPILOT_API_BOOTSTRAP=0` (parsed by [`getEnableBootstrap()`](apps/api/src/env.ts:49)).

At startup:
- Always runs `EnsureInitialData.execute()` in [`BootstrapModule.onModuleInit()`](apps/api/src/domain/bootstrap/BootstrapModule.ts:21).
- Seeds racing data via `SeedRacingData` when:
  - persistence is `inmemory`, or
  - persistence is `postgres` AND `NODE_ENV !== 'production'` AND the racing DB appears empty (checked via the league repository) in [`BootstrapModule.shouldSeedRacingData()`](apps/api/src/domain/bootstrap/BootstrapModule.ts:42).

This keeps dev environments usable without requiring manual seed steps, while avoiding unexpected reseeding in production.