Backend6 min read

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.

PrismaORMTypeScriptPostgreSQLDatabase

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

  1. 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.
  2. Run migrationsPrisma Migrate generates SQL migration files from schema changes - creating a reproducible, version-controlled DB evolution history.
  3. Query with the Prisma ClientThe generated client is fully typed - IDE autocompletes fields, TypeScript catches wrong field names at compile time.
  4. Use transactions for multi-step operationsOperations that must succeed or fail together need a transaction - Prisma's interactive transactions give full control.
  5. 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 instance

Examples

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

More skills in this library

Browse all technical skills - Mobile, AI/ML, Web, Backend, Design, and Product.