DataSource setup
src/data-source.ts:
poolSize: 10 keeps your app’s connection share at half of PgBouncer’s default_pool_size = 20, leaving room for migrations and other workloads.
If you’re using pg directly (TypeORM’s default for type: "postgres"), prepared statements aren’t enabled unless you call client.query() with the name option — which TypeORM’s repository methods don’t do. So unlike Prisma/Drizzle, no explicit prepare=false flag is needed. Just don’t switch to a driver that does auto-prepare.
Entities
src/entities/User.ts:
src/entities/Post.ts:
{ name: "users" } / { name: "created_at" } overrides map the TypeScript names to snake_case SQL — match whatever convention you’ve set for the rest of your schema.
Queries via repositories
Migrations
TypeORM has its own migration runner. Generate from current schema vs entities:src/migrations/ as TypeScript classes implementing MigrationInterface. Like Drizzle, the generated migration is largely SQL — easy to inspect before applying.
TypeORM’s tracking table is migrations. Don’t touch it.
The auto-generate caveat is worth knowing: TypeORM compares your entities against the live database schema, which means you need a development database that matches your production schema for autogenerate to produce a clean diff. Most teams keep a local Postgres pinned to production’s schema for this.
RLS from TypeORM
supabase_admin connection, bypasses RLS. For RLS-respecting queries, the same transaction-with-SET-LOCAL pattern as Prisma and Drizzle:
tx.query here is the raw-SQL escape hatch on the transactional connection.
TypeORM in NestJS
In a NestJS project, the standard wiring isTypeOrmModule.forRoot() in your app module:
Next steps
Connection pooling
The PgBouncer constraints
poolSize: 10 and disabled-prepares work around.Migrations
TypeORM’s runner in the context of the other ORMs.
Direct Postgres
For SQL TypeORM doesn’t express — bulk imports, schema introspection.
Prisma
The TypeScript ORM most teams default to today.