Different ORMs Need Different AI Rules
AI generates ORM code based on its training data — which includes both Prisma and Drizzle patterns. Without project-specific rules, the AI may: use Prisma syntax in a Drizzle project (or vice versa), apply Prisma migration patterns to Drizzle (they are fundamentally different), use Prisma include syntax when Drizzle uses leftJoin, or generate Prisma Client queries when the project uses Drizzle query builder. The ORM choice shapes every database interaction — the AI needs explicit rules to generate correct code.
Prisma is a schema-first ORM: you define models in schema.prisma (a custom DSL), Prisma generates a type-safe client, and you query via the generated Prisma Client API (prisma.user.findMany). Drizzle is a TypeScript-first ORM: you define schemas in TypeScript files, Drizzle provides a query builder that maps closely to SQL, and you query via the builder API (db.select().from(users)). Same goal (type-safe database access), different paradigms (schema DSL vs TypeScript, generated client vs query builder).
This article provides: side-by-side comparison of each ORM's approach, the AI rules needed for each, and ready-to-use rule templates you can add to your CLAUDE.md or .cursorrules. The rules prevent the AI from mixing ORM patterns and guide it toward each ORM's idiomatic code.
Schema Definition: schema.prisma vs TypeScript
Prisma schema: defined in schema.prisma using Prisma's custom DSL. model User { id String @id @default(uuid()) email String @unique name String? posts Post[] }. The schema is: separate from application code (its own file and language), used to generate the Prisma Client and TypeScript types, and the source of truth for database migrations (prisma migrate). AI rule: 'Define all models in schema.prisma. Never create database tables via raw SQL. The Prisma schema is the single source of truth for the database structure.'
Drizzle schema: defined in TypeScript files using Drizzle's table builder. export const users = pgTable('users', { id: uuid('id').primaryKey().defaultRandom(), email: text('email').notNull().unique(), name: text('name') }). The schema is: regular TypeScript (same language as the application), used directly in queries (import { users } from './schema'), and the source of truth for Drizzle Kit migrations. AI rule: 'Define all tables in src/db/schema.ts using pgTable/sqliteTable. Import table definitions directly in queries. The TypeScript schema is the single source of truth.'
The rule difference: Prisma rules must specify: use the schema.prisma file, run prisma generate after schema changes, and never bypass Prisma Client with raw queries unless absolutely necessary. Drizzle rules must specify: use pgTable in TypeScript files, import tables directly, and use the Drizzle query builder (not raw SQL) for type safety. The AI needs to know which paradigm it is working in to generate correct schema code.
- Prisma: schema.prisma DSL, prisma generate for client, prisma migrate for DB changes
- Drizzle: TypeScript pgTable, import directly in queries, drizzle-kit for migrations
- Prisma rule: 'All models in schema.prisma, run prisma generate after changes'
- Drizzle rule: 'All tables in src/db/schema.ts, import tables in query files'
- AI confusion: mixing syntax is the most common error without explicit ORM rules
Without ORM rules: AI uses Prisma include syntax in a Drizzle project. With one rule paragraph specifying the ORM, schema location, and query pattern: every AI generation uses the correct syntax. The most impactful rule you can add to any project.
Query Patterns: Client API vs Query Builder
Prisma queries: use the generated Prisma Client with method chaining. const users = await prisma.user.findMany({ where: { role: 'admin' }, include: { posts: true }, orderBy: { createdAt: 'desc' } }). Relations: include (eager load), select (pick fields). The Prisma Client API is: high-level (abstracted from SQL), relation-aware (include loads related records automatically), and type-safe (TypeScript types generated from the schema).
Drizzle queries: use the query builder that maps closely to SQL. const users = await db.select().from(usersTable).where(eq(usersTable.role, 'admin')).leftJoin(postsTable, eq(postsTable.userId, usersTable.id)).orderBy(desc(usersTable.createdAt)). Relations: leftJoin (explicit SQL join), or Drizzle relational queries (db.query.users.findMany({ with: { posts: true } })). The query builder is: SQL-transparent (you see the SQL structure), explicit (joins are written, not implied), and type-safe (inferred from the TypeScript schema).
The rule difference: Prisma rules should specify: 'Use include for relations (not raw JOINs), select for field picking, findMany/findUnique/create/update/delete methods. Avoid raw SQL ($queryRaw) unless Prisma Client cannot express the query.' Drizzle rules should specify: 'Use db.select().from().where() for queries, eq/gt/lt/like for conditions, leftJoin for relations. Use db.query for relational queries with the with syntax. Import all operators from drizzle-orm.'
Migration Workflows: prisma migrate vs drizzle-kit
Prisma migrations: prisma migrate dev generates a migration file from schema.prisma changes, applies it to the dev database, and regenerates the client. prisma migrate deploy applies pending migrations in production. Migrations are SQL files in prisma/migrations/. The workflow: edit schema.prisma, run prisma migrate dev --name description, review the generated SQL, commit. AI rule: 'After any schema.prisma change, run prisma migrate dev. Never edit migration files manually. Review generated SQL before committing.'
Drizzle migrations: drizzle-kit generate creates migration SQL from TypeScript schema changes. drizzle-kit migrate applies migrations. Migrations are SQL files in drizzle/ (configurable). The workflow: edit schema.ts, run drizzle-kit generate, review the generated SQL, run drizzle-kit migrate, commit. AI rule: 'After any schema.ts change, run drizzle-kit generate. Review the generated SQL. Run drizzle-kit migrate to apply. Never edit generated migration files.'
The migration rules are structurally similar (both: change schema, generate migration, review, apply, commit) but the commands differ. The AI must know which commands to suggest. Without the rule: AI suggests prisma migrate dev in a Drizzle project (command does not exist). With the rule: AI suggests drizzle-kit generate (correct command for the ORM in use).
- Prisma: edit schema.prisma → prisma migrate dev → review SQL → commit
- Drizzle: edit schema.ts → drizzle-kit generate → review SQL → drizzle-kit migrate → commit
- Both: schema is source of truth, migration SQL is generated, review before applying
- AI confusion: suggesting prisma commands in Drizzle projects (and vice versa)
- Rule prevents: wrong CLI commands, wrong migration workflows, wrong schema files
Both ORMs: change schema → generate migration → review SQL → apply → commit. But 'prisma migrate dev' vs 'drizzle-kit generate' — the AI must know which command to suggest. Without the rule: AI suggests Prisma commands in a Drizzle project.
Edge and Serverless Compatibility
Prisma edge compatibility: Prisma traditionally uses a Rust-based query engine that requires a binary (not edge-compatible). Prisma Accelerate and Prisma Pulse provide edge access via a proxy. Prisma also supports driver adapters for serverless databases (Neon, PlanetScale). The edge story is evolving but requires additional configuration. AI rule: 'For serverless/edge: use Prisma with the Neon driver adapter or Prisma Accelerate. Do not use the default Prisma Client in edge runtimes (binary not compatible).'
Drizzle edge compatibility: Drizzle is JavaScript/TypeScript-only (no binary engine). It works natively in: Cloudflare Workers, Vercel Edge Functions, Deno Deploy, and any V8 isolate environment. With @neondatabase/serverless: Drizzle connects via HTTP (no TCP needed). The edge story is first-class: Drizzle was designed for the serverless era. AI rule: 'Drizzle works natively at the edge. Use @neondatabase/serverless for Neon, @planetscale/database for PlanetScale. No additional configuration needed for edge runtimes.'
The edge rule is critical for modern applications. AI trained on older Prisma patterns generates code that fails at the edge (binary not available). AI trained on Drizzle patterns generates edge-compatible code by default. The rule ensures the AI knows: which ORM works where, which adapters are needed, and which connection patterns to use for serverless environments. This is the most impactful rule for projects deploying to edge runtimes.
Prisma default client uses a Rust binary that fails in edge runtimes (Cloudflare Workers, Vercel Edge). AI trained on older patterns generates code that crashes at the edge. Rule: 'Use Prisma Accelerate or driver adapter for edge.' Drizzle: edge-native, no binary, no rule needed.
Ready-to-Use Rule Templates
Prisma CLAUDE.md template: '# Database (Prisma). This project uses Prisma ORM with PostgreSQL. Schema: prisma/schema.prisma. Client: import { prisma } from "@/lib/prisma". Queries: use Prisma Client methods (findMany, findUnique, create, update, delete). Relations: use include for eager loading, select for field picking. Migrations: prisma migrate dev after schema changes. Types: use Prisma-generated types (import { User } from "@prisma/client"). Never use raw SQL unless Prisma Client cannot express the query.'
Drizzle CLAUDE.md template: '# Database (Drizzle). This project uses Drizzle ORM with Neon PostgreSQL. Schema: src/db/schema.ts using pgTable. Connection: import { db } from "@/db". Queries: db.select().from(table).where(condition). Relations: leftJoin or db.query with { with: { relation: true } }. Operators: import { eq, gt, lt, like, and, or } from "drizzle-orm". Migrations: drizzle-kit generate after schema changes. Edge-compatible: uses @neondatabase/serverless for HTTP connections.'
Copy the template for your ORM into your CLAUDE.md or .cursorrules. The template gives the AI: which ORM to use, where the schema lives, how to import the client, which query patterns to follow, how to handle relations, and which migration commands to run. One paragraph of rules prevents hundreds of ORM-confused AI generations.
Comparison Summary
Summary of Prisma vs Drizzle AI rules.
- Schema: Prisma = schema.prisma DSL vs Drizzle = TypeScript pgTable — different files, different syntax
- Queries: Prisma = Client API (findMany, include) vs Drizzle = query builder (select, leftJoin, eq)
- Migrations: prisma migrate dev vs drizzle-kit generate — similar workflow, different commands
- Edge: Drizzle native (no binary) vs Prisma needs Accelerate or driver adapter
- Type safety: both type-safe — Prisma generates types, Drizzle infers from TypeScript schema
- AI confusion: mixing syntax is the #1 error without explicit ORM rules
- Rule templates: one paragraph per ORM prevents hundreds of wrong generations
- RuleSync: ORM rules in the centralized dashboard, synced to every tool format