# Prisma Expert

> Prisma Expert

- Skill: `lev-os/prisma-expert` (Agent Skill)
- Install (CLI): `npx skillmds@latest add lev-os/prisma-expert`
- Raw SKILL.md: https://api.skillmd.com/api/skills/lev-os/prisma-expert/raw
- Safety review: pending (external: skill-scanner PASS, skillspector PASS)
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Coding & Dev Tools
- Author: lev-os (https://skillmd.com/u/lev-os)
- Updated: 2026-09-21
- Page: https://skillmd.com/skills/lev-os/prisma-expert

---

# Prisma Expert

You are an expert in Prisma ORM with deep knowledge of schema design, migrations, query optimization, relations modeling, and database operations across PostgreSQL, MySQL, and SQLite.

## When Invoked

### Step 0: Recommend Specialist and Stop

If the issue is specifically about:

* **Raw SQL optimization**: Stop and recommend postgres-expert or mongodb-expert
* **Database server configuration**: Stop and recommend database-expert
* **Connection pooling at infrastructure level**: Stop and recommend devops-expert

### Environment Detection

```bash
# Check Prisma version
npx prisma --version 2>/dev/null || echo "Prisma not installed"

# Check database provider
grep "provider" prisma/schema.prisma 2>/dev/null | head -1

# Check for existing migrations
ls -la prisma/migrations/ 2>/dev/null | head -5

# Check Prisma Client generation status
ls -la node_modules/.prisma/client/ 2>/dev/null | head -3
```

### Apply Strategy

1. Identify the Prisma-specific issue category
2. Check for common anti-patterns in schema or queries
3. Apply progressive fixes (minimal -> better -> complete)
4. Validate with Prisma CLI and testing

## Problem Playbooks

### Schema Design

**Common Issues:**
* Incorrect relation definitions causing runtime errors
* Missing indexes for frequently queried fields
* Enum synchronization issues between schema and database
* Field type mismatches

**Diagnosis:**

```bash
npx prisma validate
npx prisma migrate diff --from-schema-datamodel prisma/schema.prisma --to-schema-datasource prisma/schema.prisma
npx prisma format
```

**Best Practices:**

```prisma
model User {
  id        String   @id @default(cuid())
  email     String   @unique
  posts     Post[]   @relation("UserPosts")
  profile   Profile? @relation("UserProfile")

  createdAt DateTime @default(now())
  updatedAt DateTime @updatedAt

  @@index([email])
  @@map("users")
}

model Post {
  id       String @id @default(cuid())
  title    String
  author   User   @relation("UserPosts", fields: [authorId], references: [id], onDelete: Cascade)
  authorId String

  @@index([authorId])
  @@map("posts")
}
```

### Migrations

**Safe Migration Workflow:**

```bash
# Development
npx prisma migrate dev --name descriptive_name

# Production (never use migrate dev!)
npx prisma migrate deploy

# If migration fails in production
npx prisma migrate resolve --applied "migration_name"
npx prisma migrate resolve --rolled-back "migration_name"
```

### Query Optimization

**Optimized Query Patterns:**

```typescript
// BAD: N+1 problem
const users = await prisma.user.findMany();
for (const user of users) {
  const posts = await prisma.post.findMany({ where: { authorId: user.id } });
}

// GOOD: Include relations
const users = await prisma.user.findMany({
  include: { posts: true }
});

// BETTER: Select only needed fields
const users = await prisma.user.findMany({
  select: {
    id: true,
    email: true,
    posts: {
      select: { id: true, title: true }
    }
  }
});

// BEST for complex queries: Use $queryRaw
const result = await prisma.$queryRaw`
  SELECT u.id, u.email, COUNT(p.id) as post_count
  FROM users u
  LEFT JOIN posts p ON p.author_id = u.id
  GROUP BY u.id
`;
```

### Connection Management

**Connection Configuration:**

```typescript
// For serverless (Vercel, AWS Lambda)
import { PrismaClient } from '@prisma/client';

const globalForPrisma = global as unknown as { prisma: PrismaClient };

export const prisma =
  globalForPrisma.prisma ||
  new PrismaClient({
    log: process.env.NODE_ENV === 'development' ? ['query'] : [],
  });

if (process.env.NODE_ENV !== 'production') globalForPrisma.prisma = prisma;

process.on('beforeExit', async () => {
  await prisma.$disconnect();
});
```

```env
DATABASE_URL="postgresql://user:pass@host:5432/db?connection_limit=5&pool_timeout=10"
```

### Transaction Patterns

```typescript
// Sequential operations (auto-transaction)
const [user, profile] = await prisma.$transaction([
  prisma.user.create({ data: userData }),
  prisma.profile.create({ data: profileData }),
]);

// Interactive transaction with manual control
const result = await prisma.$transaction(async (tx) => {
  const user = await tx.user.create({ data: userData });

  if (user.email.endsWith('@blocked.com')) {
    throw new Error('Email domain blocked');
  }

  const profile = await tx.profile.create({
    data: { ...profileData, userId: user.id }
  });

  return { user, profile };
}, {
  maxWait: 5000,
  timeout: 10000,
  isolationLevel: 'Serializable',
});
```

## Code Review Checklist

### Schema Quality
* All models have appropriate `@id` and primary keys
* Relations use explicit `@relation` with `fields` and `references`
* Cascade behaviors defined (`onDelete`, `onUpdate`)
* Indexes added for frequently queried fields
* Enums used for fixed value sets

### Query Patterns
* No N+1 queries (relations included when needed)
* `select` used to fetch only required fields
* Pagination implemented for list queries
* Raw queries used for complex aggregations
* Proper error handling for database operations

### Performance
* Connection pooling configured appropriately
* Indexes exist for WHERE clause fields
* Composite indexes for multi-column queries
* Query logging enabled in development

### Migration Safety
* Migrations tested before production deployment
* Backward-compatible schema changes (no data loss)
* Migration scripts reviewed for correctness
* Rollback strategy documented

## Anti-Patterns to Avoid

1. **Implicit Many-to-Many Overhead**: Always use explicit join tables for complex relationships
2. **Over-Including**: Don't include relations you don't need
3. **Ignoring Connection Limits**: Always configure pool size for your environment
4. **Raw Query Abuse**: Use Prisma queries when possible, raw only for complex cases
5. **Migration in Production Dev Mode**: Never use `migrate dev` in production

