---
name: nextjs-prisma-postgres
description: "Use when building, refactoring, or reviewing a Next.js 16 + Prisma ORM + PostgreSQL project (Next.js, Prisma, PostgreSQL, TypeScript, Tailwind CSS). Production guidelines for Next.js App Router, Server Actions, Prisma connection pooling, PgBouncer/Neon tuning, and Zod schema validation."
license: MIT
metadata:
  source: https://stackitfast.com/rules/nextjs-prisma-postgres
  version: "2026-10-04"
---

# Next.js 16 + Prisma ORM + PostgreSQL — Agent Skill

## When to use this skill
- Any task that scaffolds, modifies, refactors, or reviews code in a Next.js 16 + Prisma ORM + PostgreSQL codebase.
- Whenever the project depends on Next.js, Prisma, PostgreSQL, TypeScript, Tailwind CSS.
- Apply these guidelines before proposing architecture, database, or deployment changes.

## Guidelines
# Project Architecture & Guidelines (Next.js 16 + Prisma + PostgreSQL)

## 1. System Architecture
- **Framework**: Next.js 16 (App Router, Server Components by default).
- **Next.js 16 specifics**: request APIs (`cookies()`, `headers()`, `params`, `searchParams`) are async, so always `await` them; request interception lives in `proxy.ts` (the renamed `middleware.ts`); Turbopack is the default bundler for dev and build.
- **Database & ORM**: PostgreSQL with Prisma ORM (`@prisma/client`, `prisma`).
- **Connection Pooling**: PgBouncer / Neon pooled connection string on port 6543 (`pgbouncer=true&connection_limit=1` for serverless Lambdas).
- **Validation & Types**: TypeScript (strict mode) + Zod for runtime schema validation.

## 2. Prisma Client & Connection Management (Critical)
- Always implement the global singleton pattern in `src/lib/prisma.ts` to prevent connection exhaustion during development HMR:
  ```typescript
  import { PrismaClient } from '@prisma/client';

  const globalForPrisma = globalThis as unknown as { prisma: PrismaClient | undefined };

  export const prisma =
    globalForPrisma.prisma ??
    new PrismaClient({
      log: process.env.NODE_ENV === 'development' ? ['query', 'error', 'warn'] : ['error'],
    });

  if (process.env.NODE_ENV !== 'production') globalForPrisma.prisma = prisma;
  ```
- Never call `$connect()` or `$disconnect()` manually inside Server Actions or route handlers.
- In production serverless environments, tune `connection_limit=1` or `connection_limit=2` in `DATABASE_URL`.
- Use `DIRECT_URL` (direct port 5432) for running migrations via `prisma migrate deploy`.

## 3. Server Actions & Mutations
- Place server mutations in `src/actions/` with `'use server'` directive.
- Parse and validate all inputs with Zod before executing Prisma queries.
- Return typed result objects: `{ success: true, data: T } | { success: false, error: string }`.
- Keep client components minimal; fetch data in React Server Components (RSC) and pass down as props.

## 4. Migration & Schema Workflow
- Schema source of truth: `prisma/schema.prisma`.
- Development: Run `bunx prisma migrate dev --name <migration_name>`.
- Production CI/CD: Run `bunx prisma migrate deploy`. NEVER use `db push` in production.
- Indexes: Explicitly define indexes (`@@index([userId, createdAt])`) for all foreign keys and frequently queried fields.

## 5. Common Pitfalls to Avoid
- ❌ Over-fetching: Avoid unconstrained `findMany()`; always pass `select` or `take` / `skip` pagination.
- ❌ N+1 Queries: Use Prisma `include` or batch queries instead of executing queries in loops.
- ❌ Exposing Database Secrets: Never prefix `DATABASE_URL` with `NEXT_PUBLIC_`.

## 6. Testing Conventions
- Use Vitest for unit tests on Server Actions; point the test Prisma client at a disposable schema or Docker Postgres instance, never a shared dev database.
- Use Playwright for e2e coverage of critical mutation flows (checkout, auth, billing) end-to-end through the real UI.
- Test Zod validation boundaries on every Server Action input schema — this is the first and cheapest layer to catch bad data.
- Run `bunx prisma validate` and `tsc --noEmit` in CI to catch schema/query drift before it reaches a migration.

## 7. Git Workflow & PR Conventions
- Conventional Commits (`feat:`, `fix:`, `refactor:`) scoped to the model or route, e.g. `fix(orders): prevent duplicate submission on double-click`.
- `prisma/migrations/` files ship in the same PR as the `schema.prisma` change that generated them — never hand-edit a generated migration.
- Require `tsc --noEmit` and `bun run build` green before merge.
- Never merge a PR containing `prisma db push` in its history against a shared environment; migrations only.

## Source
Maintained at https://stackitfast.com/rules/nextjs-prisma-postgres — also available as AGENTS.md, CLAUDE.md, and Cursor .mdc.