🦀 ClawHub
Prisma
by @ivangdavila
Write efficient Prisma queries, design schemas, and avoid common ORM pitfalls.
TERMINAL
clawhub install prisma📖 About This Skill
name: Prisma description: Write efficient Prisma queries, design schemas, and avoid common ORM pitfalls. metadata: category: database skills: ["prisma", "orm", "database", "typescript", "nodejs"]
Schema Design Traps
@default(cuid()) over @default(uuid()) for IDs—shorter, URL-safe, still unique@updatedAt doesn't update on nested writes—must touch parent record explicitly@unique on nullable field allows multiple NULLs—intended behavior but often surprisingQuery Patterns I Forget
findUniqueOrThrow / findFirstOrThrow—cleaner than null check after findUniquecreateMany skips hooks and returns count only—use create in loop if you need records backupsert requires unique field in where—can't upsert on non-unique compound conditionsconnectOrCreate in nested writes—avoids separate existence checkselect and include are mutually exclusive—can't mix; use nested select inside includeN+1 Query Prevention
include everything you'll access—check logs for unexpected queriesfindMany + include better than loop of findUnique—single query vs N queriesTransaction Gotchas
$transaction([]) array syntax rolls back all on any failure—use for atomic operations$transaction(async (tx) => {}) hold connection—keep short$transaction doesn't retry on conflict—implement retry logic for optimistic lockingType Safety Gaps
include result type doesn't narrow—TypeScript thinks relations might be undefinedunknown[]—need manual type assertion or Prisma.$queryRawJsonValue—cast needed; consider using typed JSON librariesPrisma.validator for reusable query fragments with correct types$executeRaw is count—not the affected rowsMigration Issues
prisma db push for prototyping—prisma migrate dev for version controldb push can drop data silently—never use in productionmigrate dev—needs create permission or separate DB@map to keep dataPerformance Traps
findMany without take can return millions—always paginatecount() scans table—expensive on large tables; consider approximate or cached countsinclude with large relations loads everything—use cursor pagination for big lists_count: { select: { posts: true } }—single query, not N+1orderBy on non-indexed field = slow—ensure indexes match sort patternsRaw Query Patterns
$queryRaw for reads, $executeRaw for writes—different return typesPrisma.sql template for safe interpolation—never string concatenation$queryRawUnsafe exists but name is a warning—use only for dynamic column names@map usedConnection Management
connection_limit in URL?pool_timeout=0—prevents connection exhaustion$disconnect() in scripts and tests—lambda/serverless should manage differentlyMiddleware Patterns
delete, convert to update—but deleteMany needs handling$use captures all queries—but adds latency to every operationinclude in middleware—transform happens before middlewareCommon Mistakes
await—Prisma returns promises; queries don't execute without awaitupdate without where = error—unlike some ORMs, Prisma requires explicit where@relation names must match—cryptic error if they don'tprisma migrate deploy in CI