prisma
✓Verified·Scanned 2/18/2026
This skill provides Prisma schema, query, migration, and performance best-practices, covering items like prisma db push, prisma migrate dev, findUniqueOrThrow, and $transaction. No security-relevant behaviors detected.
from clawhub.ai·va3545c9·4.7 KB·0 installs
Scanned from 1.0.0 at a3545c9 · Transparency log ↗
$ vett add clawhub.ai/ivangdavila/prisma
Schema Design Traps
@default(cuid())over@default(uuid())for IDs—shorter, URL-safe, still unique@updatedAtdoesn't update on nested writes—must touch parent record explicitly- Implicit many-to-many creates join table you can't customize—use explicit for extra fields
@uniqueon nullable field allows multiple NULLs—intended behavior but often surprising- Enum changes require migration—can't add values without downtime unless using String
Query Patterns I Forget
findUniqueOrThrow/findFirstOrThrow—cleaner than null check after findUniquecreateManyskips hooks and returns count only—usecreatein loop if you need records backupsertrequires unique field in where—can't upsert on non-unique compound conditionsconnectOrCreatein nested writes—avoids separate existence checkselectandincludeare mutually exclusive—can't mix; use nested select inside include
N+1 Query Prevention
- Default queries don't include relations—every access triggers new query
includeeverything you'll access—check logs for unexpected queries- Middleware can't see includes—adding includes in middleware doesn't help
findMany+includebetter than loop offindUnique—single query vs N queries- Dataloader pattern for GraphQL resolvers—Prisma doesn't batch automatically
Transaction Gotchas
$transaction([])array syntax rolls back all on any failure—use for atomic operations- Interactive transactions
$transaction(async (tx) => {})hold connection—keep short - Default 5s timeout on interactive transactions—increase for long operations
- Nested writes are already transactional—don't wrap single create with relations in transaction
$transactiondoesn't retry on conflict—implement retry logic for optimistic locking
Type Safety Gaps
includeresult type doesn't narrow—TypeScript thinks relations might be undefined- Raw queries return
unknown[]—need manual type assertion or Prisma.$queryRaw<Type> - JSON fields are
JsonValue—cast needed; consider using typed JSON libraries Prisma.validatorfor reusable query fragments with correct types- Return types of
$executeRawis count—not the affected rows
Migration Issues
prisma db pushfor prototyping—prisma migrate devfor version controldb pushcan drop data silently—never use in production- Shadow database required for
migrate dev—needs create permission or separate DB - Renaming field = drop + create by default—use
@mapto keep data - Large table migrations lock table—consider running raw SQL with concurrent indexes
Performance Traps
findManywithouttakecan return millions—always paginatecount()scans table—expensive on large tables; consider approximate or cached countsincludewith large relations loads everything—use cursor pagination for big lists- Relation counts:
_count: { select: { posts: true } }—single query, not N+1 orderByon non-indexed field = slow—ensure indexes match sort patterns
Raw Query Patterns
$queryRawfor reads,$executeRawfor writes—different return types- Use
Prisma.sqltemplate for safe interpolation—never string concatenation - Raw queries bypass Prisma hooks and middleware—intentional but easy to forget
$queryRawUnsafeexists but name is a warning—use only for dynamic column names- Raw results use database column names—not Prisma field names if
@mapused
Connection Management
- Default pool size 5—too low for production; set
connection_limitin URL - PlanetScale/serverless needs
?pool_timeout=0—prevents connection exhaustion $disconnect()in scripts and tests—lambda/serverless should manage differently- Prisma Accelerate or Data Proxy for edge/serverless—direct DB connections don't scale
Middleware Patterns
- Soft delete via middleware: intercept
delete, convert toupdate—butdeleteManyneeds handling - Audit logging:
$usecaptures all queries—but adds latency to every operation - Middleware runs in order added—earlier middleware sees raw params
- Can't modify
includein middleware—transform happens before middleware
Common Mistakes
- Forgetting
await—Prisma returns promises; queries don't execute without await updatewithout where = error—unlike some ORMs, Prisma requires explicit where- Decimal fields return strings—Prisma Decimal type, not JavaScript number
@relationnames must match—cryptic error if they don't- Schema drift: production differs from migrations—run
prisma migrate deployin CI