Skip to main content
TypeORM is a decorator-based TypeScript ORM, popular in NestJS apps and other framework-first stacks. Its model definitions and migration runner work well with Powabase as long as you turn off TypeORM’s prepared-statement caching at the pooler level. For pooler-level constraints, see Connection pooling. For migration patterns shared across ORMs, see Migrations.

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 and 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:
The { 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

For complex queries, use the QueryBuilder. It’s the closest TypeORM gets to raw SQL:

Migrations

TypeORM has its own migration runner. Generate from current schema vs entities:
Migrations land in src/migrations/ as TypeScript classes implementing MigrationInterface. As with Drizzle, the generated migration is largely SQL, so it’s easy to inspect before applying. TypeORM’s tracking table is migrations. Don’t touch it. One autogenerate caveat is worth knowing: TypeORM compares your entities against the live database schema, so 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:
Inside the transaction, RLS applies. The tx.query calls here are the raw-SQL escape hatch on the transactional connection.

TypeORM in NestJS

In a NestJS project, the standard wiring is TypeOrmModule.forRoot() in your app module:
Then inject repositories into your services:
NestJS handles the request-scoped lifecycle, so you don’t need to think about checkouts.

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.