1---2name: nestjs-database3description: Data access patterns, Scaling, Migrations, and ORM selection.4---56# NestJS Database Standards78## Selection Framework910### 1. Data Structure Analysis (The "What")1112- **Structured & Highly Related**: Users, Orders, Inventory, Financials.13 - **Choice**: **PostgreSQL** (Default).14 - _Why_: Strict schema validation, ACID transactions, complex generic queries (Joins).15- **Unstructured / Polymorphic**: Product Catalogs (lots of unique attributes), CMS Content, Raw JSON blobs.16 - **Choice**: **MongoDB**.17 - _Why_: Schema flexibility, fast development speed for flexible data models.18- **Time-Series / Metrics**: IoT Sensor Data, Stock Prices, Server Logs.19 - **Choice**: **TimescaleDB** (Postgres Extension).20 - _Why_: Compression, hypertable partitioning, rapid ingestion.2122### 2. Access Pattern Analysis (The "How")2324- **Transactional (OLTP)**: "User buys items to cart".25 - **Requirement**: Strong Consistency (ACID). **SQL** is mandatory.26- **Analytical (OLAP)**: "Dashboard showing sales trends".27 - **Requirement**: Aggregation speed. Columnar storage (ClickHouse) or Read Replicas.28- **High Throughput Write**: "1M events/sec".29 - **Requirement**: Append-only speed. **Cassandra** / **DynamoDB** (Leaderless replication).3031### 3. Decision Matrix3233| Feature Needed | Primary Choice | Alternative |34| :--------------------- | :---------------- | :--------------------- |35| General Purpose App | **PostgreSQL** | MySQL |36| Flexible JSON Docs | **MongoDB** | PostgreSQL (JSONB) |37| Search Engine | **ElasticSearch** | PostgreSQL (Full Text) |38| Financial Transactions | **PostgreSQL** | (None) |3940## Patterns4142- **Repository Pattern**: Isolate database logic.43 - **TypeORM**: Inject `@InjectRepository(Entity)`.44 - **Prisma**: Create a comprehensive `PrismaService`.45- **Abstraction**: Services should call Repositories, not raw SQL queries.4647## Configuration (TypeORM)4849- **Async Loading**: Always use `TypeOrmModule.forRootAsync` to load secrets from `ConfigService`.50- **Sync**: Set `synchronize: false` in production; use migrations instead.5152## Scaling & Production5354- **Read Replicas**: Configure separate `replication` connections (Master for Write, Slaves for Read) in TypeORM/Prisma to distribute load.55- **Connection Multiplexing**:56 - **Problem**: Scaling K8s pods to 100+ exhausts DB connection limits (100 pods \* 10 connections = 1000 conns).57 - **Solution**: Use **PgBouncer** (Postgres) or **ProxySQL** (MySQL) in transaction mode. Do NOT rely solely on ORM pooling.58- **Migrations**:59 - **NEVER** run `synchronize: true` in production.60 - **Execution**: Run migrations via a dedicated "init container" or CD job step. Do **NOT** auto-run inside the main app process on startup (race conditions when scaling to multiple pods).61- **Soft Deletes**: Use `@DeleteDateColumn` (TypeORM) or middleware (Prisma) to preserve data integrity.6263## Architectures (Multi-Tenancy & Sharding)6465- **Column-Based (SaaS Standard)**: Single DB, `tenant_id` column.66 - _Scale_: High. _Isolation_: Low.67 - _Code_: Requires Row-Level Security (RLS) policies or strict `Where` scopes.68- **Schema-Based**: One DB, one Schema per Tenant.69 - _Scale_: Medium. _Isolation_: Medium. Good for B2B.70- **Database-Based**: One DB per Tenant.71 - _Scale_: Low (max ~500 tenants per cluster). _Isolation_: High.72 - _Code_: Requires "Connection Switching" middleware. Complex.73- **Horizontal Sharding**:74 - **Logic**: Shard massive tables by a key (e.g. `user_id`) across physical nodes to exceed single-node write limits.75 - **Complexity**: Extreme. Avoid until >10TB data. Use "Partitioning" first.76- **Partioning (Postgres)**:77 - **Strategy**: Use native Table Partitioning (e.g., by range/date) for massive tables (Logs, Audit, Events).78 - **App Logic**: Ensure partition keys (e.g., `created_at`) are included in `WHERE` clauses to enable "Partition Pruning".7980## Migrations & Data Evolution8182- **Separation**:83 - **Schema Migrations (DDL)**: Structural changes (`CREATE TABLE`, `ADD COLUMN`). Fast. Run before app deploy.84 - **Data Migrations (DML)**: transforming data (`UPDATE users SET name = ...`). Slow. Run as background jobs or separate scripts purely to avoid locking tables for too long.85- **Zero-Downtime Field Migration (Expand-Contract Pattern)**:86 1. **Expand**: Add new column `new_field` (nullable). Deploy App v1 (Writes to both `old` and `new`).87 2. **Migrate**: Backfill data from `old` to `new` in batches (background script).88 3. **Contract**: Deploy App v2 (Reads/Writes only `new`). Drop `old_field` in next schema migration.89- **Seeding**:90 - **Dev**: Use factories (`@faker-js/faker`) to generate mock data.91 - **Prod**: Only seed static dictionaries (Roles, Countries) using "Upsert" logic to prevent duplicates.9293## Best Practices94951. **Pagination**: Mandatory. Use limit/offset or cursor-based pagination.962. **Indexing**: Define indexes in code (decorators/schema) for frequently filtered columns (`where`, `order by`).973. **Transactions**: Use `QueryRunner` (TypeORM) or `$transaction` (Prisma) for all multi-step mutations to ensure atomicity.