install
source · Clone the upstream repo
git clone https://github.com/Intense-Visions/harness-engineering
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/Intense-Visions/harness-engineering "$T" && mkdir -p ~/.claude/skills && cp -r "$T/agents/skills/codex/drizzle-with-nextjs" ~/.claude/skills/intense-visions-harness-engineering-drizzle-with-nextjs-7b3948 && rm -rf "$T"
manifest:
agents/skills/codex/drizzle-with-nextjs/SKILL.mdsource content
Drizzle with Next.js
Integrate Drizzle with Next.js using Neon/Vercel Postgres, edge runtime, and connection pooling
When to Use
- Setting up Drizzle ORM in a Next.js application
- Connecting to PostgreSQL from serverless/edge environments
- Configuring connection pooling for Vercel deployments
- Using Drizzle in Server Components, Server Actions, and Route Handlers
Instructions
- Install dependencies for your database provider:
# Neon (serverless PostgreSQL) npm install drizzle-orm @neondatabase/serverless npm install -D drizzle-kit # Vercel Postgres npm install drizzle-orm @vercel/postgres npm install -D drizzle-kit # node-postgres (standard) npm install drizzle-orm pg npm install -D drizzle-kit @types/pg
- Create the database client with singleton pattern for Next.js hot reload:
// src/db/index.ts import { drizzle } from 'drizzle-orm/neon-http'; import { neon } from '@neondatabase/serverless'; import * as schema from './schema'; const sql = neon(process.env.DATABASE_URL!); export const db = drizzle(sql, { schema });
For development with hot module reload, use a global singleton:
// src/db/index.ts import { drizzle, NeonHttpDatabase } from 'drizzle-orm/neon-http'; import { neon } from '@neondatabase/serverless'; import * as schema from './schema'; const globalForDb = globalThis as unknown as { db: NeonHttpDatabase<typeof schema>; }; if (!globalForDb.db) { const sql = neon(process.env.DATABASE_URL!); globalForDb.db = drizzle(sql, { schema }); } export const db = globalForDb.db;
- Use in Server Components — query directly:
// app/users/page.tsx import { db } from '@/db'; import { users } from '@/db/schema'; export default async function UsersPage() { const allUsers = await db.query.users.findMany({ orderBy: (users, { desc }) => [desc(users.createdAt)], }); return <UserList users={allUsers} />; }
- Use in Server Actions:
// app/users/actions.ts 'use server'; import { db } from '@/db'; import { users } from '@/db/schema'; import { eq } from 'drizzle-orm'; import { revalidatePath } from 'next/cache'; export async function updateUserName(userId: string, name: string) { await db.update(users).set({ name }).where(eq(users.id, userId)); revalidatePath('/users'); }
- Use in Route Handlers:
// app/api/users/route.ts import { db } from '@/db'; import { users } from '@/db/schema'; import { NextResponse } from 'next/server'; export async function GET() { const allUsers = await db.query.users.findMany(); return NextResponse.json(allUsers); }
- Configure drizzle-kit for migrations:
// drizzle.config.ts import { defineConfig } from 'drizzle-kit'; export default defineConfig({ schema: './src/db/schema.ts', out: './drizzle', dialect: 'postgresql', dbCredentials: { url: process.env.DATABASE_URL!, }, });
- Run migrations at build time or application start:
{ "scripts": { "db:generate": "drizzle-kit generate", "db:migrate": "drizzle-kit migrate", "db:push": "drizzle-kit push", "db:studio": "drizzle-kit studio" } }
- Edge runtime compatibility — use the HTTP-based Neon driver for edge:
// For edge runtime (middleware, edge API routes) import { drizzle } from 'drizzle-orm/neon-http'; import { neon } from '@neondatabase/serverless'; // For Node.js runtime (standard API routes, Server Components) import { drizzle } from 'drizzle-orm/neon-serverless'; import { Pool, neonConfig } from '@neondatabase/serverless';
Details
Next.js serverless functions create a new runtime per invocation. Without connection pooling, each invocation opens (and may not close) a database connection, exhausting the connection limit.
Driver selection:
— uses HTTP protocol, works in Edge Runtime, one query per request (no transactions), lowest latency for single queriesneon-http
— uses WebSocket protocol, supports transactions, works in both Edge and Node.js runtimesneon-serverless
— standard PostgreSQL driver, Node.js only, supports everything, requires connection pooling for serverlessnode-postgres
Connection pooling strategies:
- Neon built-in pooler — append
to the connection string. Uses PgBouncer on Neon's infrastructure?pooling=true - Vercel Postgres — built-in pooling via
@vercel/postgres - External PgBouncer — use a
for migrations and a pooledDIRECT_URL
for runtime queriesDATABASE_URL
Environment variables pattern:
# Pooled connection for runtime queries DATABASE_URL="postgresql://user:pass@host/db?sslmode=require" # Direct connection for migrations (bypasses pooler) DIRECT_URL="postgresql://user:pass@direct-host/db?sslmode=require"
Trade-offs:
is the fastest single-query driver but cannot run transactions — useneon-http
if you need multi-statement transactionsneon-serverless- The global singleton pattern prevents connection exhaustion during development hot reload but is not needed in production
- Edge Runtime has no
access — run migrations via CLI or in a Node.js environment, not at edge request timefs
Source
https://orm.drizzle.team/docs/get-started-postgresql
Process
- Read the instructions and examples in this document.
- Apply the patterns to your implementation, adapting to your specific context.
- Verify your implementation against the details and edge cases listed above.
Harness Integration
- Type: knowledge — this skill is a reference document, not a procedural workflow.
- No tools or state — consumed as context by other skills and agents.
Success Criteria
- The patterns described in this document are applied correctly in the implementation.
- Edge cases and anti-patterns listed in this document are avoided.