Drizzle ORM Prompt Pack

What This Pack Solves

Drizzle ORM has a small but critical set of patterns that AI tools consistently get wrong: incorrect import paths for the Neon serverless driver, wrong relation syntax, misuse of drizzle-kit push vs generate+migrate, and type errors when building dynamic queries.

These prompts give Claude and Cursor the exact context to generate correct, idiomatic Drizzle code without the back-and-forth debugging cycle.

When To Use

  • You're starting a new Drizzle schema from scratch
  • AI keeps generating Prisma patterns in your Drizzle codebase
  • You need correct relation definitions that work with with in queries
  • You're unsure when to use push vs generate + migrate
  • You need type-safe dynamic queries or transactions

Prompts

Prompt 1: Project Context Block

Use this at the start of every Drizzle-related conversation.

prompt
I'm using Drizzle ORM with Neon serverless PostgreSQL in a Next.js 15 App Router project.
 
Setup:
- Driver: @neondatabase/serverless (not 'pg' or 'postgres')
- DB client: import { db } from '@/lib/db' — already configured
- Schema files: src/lib/db/schema.ts (or schema/*.ts)
- Migrations: managed with drizzle-kit
 
Key rules:
- Use pgTable() from 'drizzle-orm/pg-core' for all table definitions
- Import { eq, and, or, desc, asc, sql } from 'drizzle-orm' for operators


When to use: Start of any conversation about your database layer.


Prompt 2: Schema Definition

prompt
I need a Drizzle schema for [describe your data model].
 
Requirements:
- Use pgTable() from 'drizzle-orm/pg-core'
- Primary keys: use uuid() with .defaultRandom() OR serial() — I'll tell you which
- Timestamps: createdAt and updatedAt on every table, use timestamp() with { withTimezone: true }
- updatedAt should use .$onUpdate(() => new Date())
- Foreign keys: reference the parent table column directly
- Export the table AND the inferred TypeScript types (Select and Insert variants)
 
Tables needed:
[describe each table and its fields, relationships, and any constraints]
 
Also define the relations() for each table so I can use the 'with' syntax in queries.

Expected output: Complete schema with table definitions, relations, and exported TypeScript types.


Prompt 3: Querying with Relations

prompt
I need to query [describe what you want to fetch] using Drizzle's relational query API.
 
My schema has these relations already defined:
[paste your relations() definitions]
 
Requirements:
- Use db.query.[tableName].findMany() or findFirst() — not db.select()
- Include related data with the 'with' key
- Filter with the 'where' key using operators from 'drizzle-orm'
- Limit and offset for pagination if needed
- The return type should be inferred — don't write manual return type interfaces
 
Query goal: [describe exactly what data you need and any filters]

Expected output: A typed relational query using Drizzle's query API with correct with nesting.


Prompt 4: Mutations (Insert, Update, Delete)

prompt
I need Drizzle mutations for [describe the operation].
 
Requirements:
- Insert: use db.insert(table).values({...}).returning()
- Update: use db.update(table).set({...}).where(eq(table.id, id)).returning()
- Delete: use db.delete(table).where(eq(table.id, id))
- Always use .returning() on insert/update so I get the created/updated record back
- Infer the insert type: type NewUser = typeof users.$inferInsert
- Wrap in try/catch — throw a typed error on constraint violations
 
Operation: [describe what you're inserting/updating/deleting]
Data shape: [describe the input fields and types]

Expected output: Type-safe insert/update/delete with .returning() and error handling.


Prompt 5: Migrations with drizzle-kit

prompt
Explain the correct migration workflow for my Drizzle + Neon setup.
 
My setup:
- drizzle.config.ts is configured with dialect: 'postgresql' and Neon connection string
- Schema is in src/lib/db/schema.ts
 
I need to understand:
1. When to use 'pnpm drizzle-kit push' vs 'pnpm drizzle-kit generate' + 'pnpm drizzle-kit migrate'
2. How to safely apply a schema change [describe the change] to production
3. Whether this change is destructive (column removal, rename, type change)
4. What the migration SQL will look like before I run it
 
Schema change I need to make: [describe what you're adding/changing/removing]

Expected output: Correct migration command sequence with explanation of destructive vs safe changes.


Prompt 6: Transactions and Upserts

prompt
I need [a transaction / an upsert] in Drizzle.
 
[For transactions]:
I need to perform multiple writes atomically:
1. [describe first operation]
2. [describe second operation]
3. [describe third operation]
If any step fails, all changes should be rolled back.
 
Use db.transaction(async (tx) => { ... }) — pass tx instead of db to all operations inside.
 
[For upserts]:
I need to insert a record if it doesn't exist, or update it if it does.
Conflict target: [describe the unique column(s)]
On conflict: [describe what fields to update]
 
Use db.insert(table).values({...}).onConflictDoUpdate({ target: table.column, set: {...} })

Expected output: Correct transaction with rollback, or typed upsert with conflict handling.


Tuning Notes

  • Always specify your driver@neondatabase/serverless is not the same as pg. Wrong driver = broken serverless deployment.
  • Specify query API vs core — Say "use relational query API (db.query)" or "use core API (db.select)". They have different syntax and AI mixes them up.
  • Paste your schema — For queries and mutations, paste the relevant table definitions. AI generates much better code when it can see the actual column names and types.
  • Name your version — Drizzle changed the relations API between minor versions. Say "Drizzle ORM latest" to avoid outdated patterns.

Common Failure Modes

  • Wrong import path for Neon — AI often writes import { Pool } from 'pg' instead of import { neon } from '@neondatabase/serverless'. Explicitly say "Neon serverless driver."
  • Relations defined inside the table — Drizzle relations are defined separately with relations(), not inside pgTable(). AI sometimes generates Prisma-style inline relations.
  • Missing .returning() — AI sometimes omits .returning() on inserts, giving you no data back. Always specify this in your prompt.
  • Using db.select when you want relational queries — The core API (db.select().from()) doesn't support the with syntax. Use db.query for relational fetching.