---
name: prisma-orm-pro
description: "Prisma schemas, migrations, relations, transactions, and the patterns that scale past 10k requests/min. Production Prisma 6: schema design, relation modes, migrations (deploy vs dev), transactions (interactive + batch), connection pooling for serverless, Prisma Accelerate setup, and the patterns to avoid the N+1 query trap."
license: MIT
---

# Prisma ORM Pro

A focused skill for building and operating Prisma in production — schema modeling, migrations, transactions, and the query patterns that hold up under serverless load and high request volume. It targets TypeScript backend engineers running Prisma 6 against Postgres (or MySQL) who keep hitting the same walls: connection exhaustion on Lambda, accidental N+1 queries, and migrations that work in dev but stall on deploy.

## When to use it

- You're designing a `schema.prisma` with non-trivial relations (many-to-many, self-relations, composite keys) and want the `@relation` wiring correct the first time.
- Your serverless functions are throwing `too many connections` or `Can't reach database server`.
- A list endpoint is slow and you suspect a hidden per-row query.
- You need to choose between `migrate dev` and `migrate deploy`, or recover from a failed/drifted migration.
- You're adding interactive transactions and need correct isolation and timeout handling.

## What it does

It works against the real Prisma surface area: the `prisma` CLI (`migrate dev`, `migrate deploy`, `migrate resolve`, `db push`, `generate`, `studio`), the `schema.prisma` file (`datasource`, `generator`, `relationMode = "prisma"` vs `"foreignKeys"`), and PrismaClient runtime APIs. On the query side it pushes you toward `include`/`select` and relation loading to kill N+1, batch transactions via `prisma.$transaction([...])`, and interactive transactions via `prisma.$transaction(async (tx) => {...}, { timeout, isolationLevel })`. For scale it covers connection pooling through the `?connection_limit=` and `?pgbouncer=true` params, the `@prisma/adapter-*` driver adapters, and **Prisma Accelerate** (`@prisma/extension-accelerate`) for connection pooling plus query-level `cacheStrategy`.

## Example

```bash
curl -fsSL --create-dirs -o ~/.claude/skills/prisma-orm-pro/SKILL.md https://claudeskil.com/skills/prisma-orm-pro/SKILL.md

# dev: create + apply a migration from schema changes
npx prisma migrate dev --name add_orders

# prod: apply already-generated migrations, no prompts
npx prisma migrate deploy
```

```ts
// Accelerate + a cached, relation-loaded query (no N+1)
import { PrismaClient } from '@prisma/client'
import { withAccelerate } from '@prisma/extension-accelerate'

const prisma = new PrismaClient().$extends(withAccelerate())

const users = await prisma.user.findMany({
  include: { orders: true },              // single JOIN-style fetch
  cacheStrategy: { ttl: 60, swr: 30 },    // Accelerate edge cache
})
```

## Tips & gotchas

- `relationMode = "prisma"` skips DB-level foreign keys (needed for PlanetScale) but means Prisma emulates referential actions and you must add `@@index` on FK columns yourself.
- Never run `migrate dev` in CI/prod — it can reset the database. Use `migrate deploy`.
- In serverless, instantiate **one** PrismaClient per container (module scope), not per request, and cap `connection_limit` low (often 1–5) behind a pooler.
- A failed migration blocks all future deploys until you run `prisma migrate resolve --applied` or `--rolled-back`.

## FAQ

**`db push` or `migrate dev`?** `db push` syncs schema to DB with no migration history — good for prototyping. Use `migrate dev` once you need versioned, reviewable migrations.

**How do I find an N+1?** Set `log: ['query']` on PrismaClient; repeated identical `SELECT`s per row mean you should fold the relation into one `include`/`select`.

**Do I still need PgBouncer with Accelerate?** No — Accelerate provides the pool. Use one or the other, and set `pgbouncer=true` when going through PgBouncer directly.
