drizzle-best-practices

Guides Drizzle ORM schema design, queries, and migrations for PostgreSQL monorepos.

Updated Aug 2, 2026
One-click install
npx skills add https://github.com/leonardoacosta/skills --skill drizzle-best-practices-leonardoacosta
Or copy as Structured Prompt for Agent▼
Please help me install this Agent Skill.
Skill: drizzle-best-practices
Source: https://github.com/leonardoacosta/skills/tree/main/t3-stack-kit/skills/drizzle-best-practices
Command: npx skills add https://github.com/leonardoacosta/skills --skill drizzle-best-practices-leonardoacosta

SYSTEM DOCUMENTATION & REQUIREMENTS

What problem does it solve? Drizzle ORM has non-obvious behaviors—silent missing relations, misleading nullability, destructive column renames, and db:push drift—that cause data loss and production incidents in T3 Turbo + PostgreSQL (Neon) monorepos. This Skill encodes the correct patterns so agents avoid these traps. ## Core Features & Use Cases - Schema Design Rules: Primary key strategy (serial vs uuid vs cuid2), branded column types with .$type<>(), and correct pairing of foreign keys with relations(). - Query Patterns: findFirst undefined semantics, explicit with: eager loading, N+1 tradeoffs, .prepare() for hot paths, and raw SQL escape hatches. - Migration Safety: Enforces migration-file-only workflows (never db:push), multi-deploy safe column renames, zero-downtime column additions, and --custom data migrations. - Use Case: When asked to rename a column in packages/db/src/schemas/, the agent generates a multi-step migration (add nullable column, backfill, switch code, drop old column) instead of a destructive single-step rename. ## Quick Start Review my Drizzle schema changes in packages/db and generate a safe migration plan for renaming the user email column.

Frequently Asked Questions about drizzle-best-practices

High-intent search queries and answers about installing and using this skill.

FAQPage Schema
How do I safely rename a column in Drizzle ORM?▼

Never rename directly—Drizzle generates DROP COLUMN plus ADD COLUMN, destroying data. Instead add a new nullable column, deploy and backfill with UPDATE, switch all code to the new name, then drop the old column in a final migration.

Why does db.query with the with option return missing relations?▼

The with option only works when relations() is defined for the table; without it, Drizzle silently returns no joined data and no error. Always pair relations() definitions with the corresponding foreign key constraints.

Should I use drizzle-kit push or generate for schema changes?▼

Always use drizzle-kit generate to produce reviewable SQL migration files applied via db:migrate. db:push skips the migrations journal, can silently drop or alter columns, and collides with deploy-time migration replay causing drift.

Does findFirst in Drizzle return null or undefined?▼

findFirst returns undefined when no row matches, not null. Guard results with if (!user) rather than if (user === null) to handle missing records correctly.

When should I use serial, uuid, or cuid2 for primary keys in Drizzle?▼

Use serial for internal high-volume tables, uuid for cross-service or externally visible IDs, and cuid2 for user-facing URL-safe slugs. Note that cuid2 via $defaultFn is TypeScript-only, so raw SQL inserts must supply the value.