mcpField
D
drizzle-postgres

drizzle-postgres

github.com/pedronauckData & databases644248 installsUpdated 1w ago
Repository

About drizzle-postgres

A practical reference skill for building type-safe PostgreSQL applications with Drizzle ORM. It helps developers model schemas, write queries, manage migrations, and diagnose performance issues.

Key features

  1. 01Schema and relationship patterns
  2. 02Typed query examples
  3. 03Migration command guidance
  4. 04Query performance checks
  5. 05PostgreSQL reference topics

Use cases

  1. 01Modeling one-to-many or many-to-many data
  2. 02Avoiding N+1 queries with relational queries
  3. 03Generating and applying schema migrations
  4. 04Investigating slow queries and indexing

Install

Copy the command and run it in a terminal.

$npx skills add https://github.com/pedronauck/skills --skill drizzle-postgres

After installing, type/drizzle-postgresin Claude Code to confirm it loaded.

Bundled files

References and scripts installed along with SKILL.md.

references/
CHEATSHEET.md
MIGRATIONS.md
PERFORMANCE.md
POSTGRES.md
QUERIES.md
RELATIONS.md
SCHEMA.md

Details

From the project README

PostgreSQL + Drizzle ORM

Type-safe database applications with PostgreSQL 18 and Drizzle ORM.

Essential Commands

npx drizzle-kit generate   # Generate migration from schema changes
npx drizzle-kit migrate    # Apply pending migrations
npx drizzle-kit push       # Push schema directly (dev only!)
npx drizzle-kit studio     # Open database browser

Quick Decision Trees

"How do I model this relationship?"
Relationship type?
├─ One-to-many (user has posts)     → FK on "many" side + relations()
├─ Many-to-many (posts have tags)   → Junction table + relations()
├─ One-to-one (user has profile)    → FK with unique constraint
└─ Self-referential (comments)      → FK to same table
"Why is my query slow?"
Slow query?
├─ Missing index on WHERE/JOIN columns  → Add index
├─ N+1 queries in loop                  → Use relational queries API
├─ Full table scan                      → EXPLAIN ANALYZE, add index
├─ Large result set                     → Add pagination (limit/offset)
└─ Connection overhead                  → Enable connection pooling
"Which drizzle-kit command?"
What do I need?
├─ Schema changed, need SQL migration   → drizzle-kit generate
├─ Apply migrations to database         → drizzle-kit migrate
├─ Quick dev iteration (no migration)   → drizzle-kit push
└─ Browse/edit data visually            → drizzle-kit studio

Directory Structure

src/db/
├── schema/
│   ├── index.ts          # Re-export all tables
│   ├── users.ts          # Table + relations
│   └── posts.ts          # Table + relations
├── db.ts                 # Connection with pooling
└── migrate.ts            # Migration runner
drizzle/
└── migrations/           # Generated SQL files
drizzle.config.ts         # drizzle-kit config

Schema Patterns

Basic Table with Timestamps
export const users = pgTable("users", {
  id: uuid("id").primaryKey().defaultRandom(),
  email: varchar("email", { length: 255 }).notNull().unique(),
  createdAt: timestamp("created_at").defaultNow().notNull(),
  updatedAt: timestamp("updated_at").defaultNow().notNull(),
});
Foreign Key with Index
export const posts = pgTable(
  "posts",
  {
    id: uuid("id").primaryKey().defaultRandom(),
    userId: uuid("user_id")
      .notNull()
      .references(() => users.id),
    title: varchar("title", { length: 255 }).notNull(),
  },
  (table) => [
    index("posts_user_id_idx").on(table.userId), // ALWAYS index FKs
  ],
);
Relations
export const usersRelations = relations(users, ({ many }) => ({
  posts: many(posts),
}));

export const postsRelations = relations(posts, ({ one }) => ({
  author: one(users, { fields: [posts.userId], references: [users.id] }),
}));

Query Patterns

Relational Query (Avoid N+1)
// ✓ Single query with nested data
const usersWithPosts = await db.query.users.findMany({
  with: { posts: true },
});
Filtered Query
const activeUsers = await db
  .select()
  .from(users)
  .where(eq(users.status, "active"));
Transaction
await db.transaction(async (tx) => {
  const [user] = await tx.insert(users).values({ email }).returning();
  await tx.insert(profiles).values({ userId: user.id });
});

Performance Checklist

PriorityCheckImpact
CRITICALIndex all foreign keysPrevents full table scans on JOINs
CRITICALUse relational queries for nested dataAvoids N+1
HIGHConnection pooling in productionReduces connection overhead
HIGHEXPLAIN ANALYZE slow queriesIdentifies missing indexes
MEDIUMPartial indexes for filtered subsetsSmaller, faster indexes
MEDIUMUUIDv7 for PKs (PG18+)Better index locality

Anti-Patterns (CRITICAL)

Anti-PatternProblemFix
No FK indexSlow JOINs, full scansAdd index on every FK column
N+1 in loopsQuery per rowUse with: relational queries
No poolingConnection per requestUse @neondatabase/serverless or similar
push in prodData loss riskAlways use generate + migrate
Storing JSON as textNo validation, bad queriesUse jsonb() column type

Reference Documentation

FilePurpose
references/SCHEMA.mdColumn types, constraints
references/QUERIES.mdOperators, joins, aggregations
references/RELATIONS.mdOne-to-many, many-to-many
references/MIGRATIONS.mddrizzle-kit workflows
references/POSTGRES.mdPG18 features, RLS, partitioning
references/PERFORMANCE.mdIndexing, optimization
references/CHEATSHEET.mdQuick reference

Resources

Drizzle ORM
PostgreSQL

Comments

Markdown supported