Prisma ORM
Type-safe ORM for Node.js and TypeScript - Prisma schema generates the DB, the client, and all types, eliminating manual SQL and migration management.
skill: Prisma ORM category: Backend tags: [Prisma, ORM, TypeScript, PostgreSQL, Database] readingTime: 6
Prisma is the best ORM for TypeScript projects - the generated client provides full type safety end-to-end, from schema to query result. Drizzle ORM is a lighter alternative with more SQL control. Raw SQL (node-postgres, pg) is better when you need complex queries or Prisma's abstraction layer gets in the way.
Workflow
- Define the schemaThe Prisma schema is the single source of truth - it defines models, relations, and database provider, then generates migrations and the typed client.
- Run migrationsPrisma Migrate generates SQL migration files from schema changes - creating a reproducible, version-controlled DB evolution history.
- Query with the Prisma ClientThe generated client is fully typed - IDE autocompletes fields, TypeScript catches wrong field names at compile time.
- Use transactions for multi-step operationsOperations that must succeed or fail together need a transaction - Prisma's interactive transactions give full control.
- Paginate with cursor-based paginationOffset pagination (`skip`) degrades at large offsets - the DB must skip millions of rows. Cursor pagination stays fast regardless of dataset size.
Output Format
Prisma project: schema → migration → type-safe queries → transactions.
prisma/
├── schema.prisma # Models, relations, DB config
└── migrations/
└── 20260805_init/ # SQL migration files
lib/
└── prisma.ts # Singleton PrismaClient instanceExamples
Input
Output
Edge Cases & Gotchas
- N+1 in nested includes - Deeply nested includes trigger multiple queries. Check with prisma.$on('query', e => console.log(e.query)) and restructure with explicit joins when needed.
- Migration conflicts in teams - Two developers creating migrations simultaneously causes a conflict. Always pull and migrate before creating a new migration on a shared branch.
- Prisma in serverless / edge - PrismaClient maintains a connection pool - not suitable for serverless functions that create many short-lived instances. Use Prisma Accelerate or @prisma/adapter-planetscale for edge.
- Raw queries for complex SQL - Prisma's query builder can't express all SQL. Use prisma.$queryRaw`SELECT ...` for complex CTEs, window functions, or full-text search.
When to Break These Rules
- Use Drizzle ORM when you want SQL-like control with TypeScript types but less abstraction than Prisma - Drizzle has no runtime query builder overhead.
- Use raw pg/postgres.js when your queries are highly complex or you need connection-level control that ORMs abstract away.
Reference Files
https://www.prisma.io/docs/https://www.prisma.io/docs/orm/prisma-client/queries/transactions