configuring-serverless-clients
npx skills add https://github.com/djankies/claude-configs --skill configuring-serverless-clients
Agent 安装分布
Skill 文档
Serverless PrismaClient Configuration
Configure PrismaClient for serverless platforms to prevent connection pool exhaustion using connection limits and global singleton patterns.
Activation Triggers
Deploy to Next.js (App/Pages Router), AWS Lambda, Vercel, or similar serverless platforms; encountering P1017 errors; files in app/, pages/api/, lambda/ directories.
Problem & Solution
Problem: Each Lambda instance creates its own connection pool. Default unlimited pool à instances exhausts database (e.g., 10 instances à 10 connections = 100 connections).
Solution: Set connection_limit=1 in DATABASE_URL; use global singleton to reuse client across invocations; consider PgBouncer for high concurrency.
Configuration Workflow
Phase 1âEnvironment: Add connection_limit=1 and pool_timeout=20 to DATABASE_URL in .env; configure in Vercel dashboard if applicable.
Phase 2âClient Singleton: Create single global PrismaClient in lib/prisma.ts; use globalThis pattern (Next.js 13+ App Router), global.prisma pattern (Pages Router/Lambda), or initialize outside handler (Lambda standalone).
Phase 3âValidation: Verify DATABASE_URL contains connection parameters; confirm new PrismaClient() appears only in lib/prisma.ts; test with 10+ concurrent requests; monitor connection count.
Implementation Patterns
Next.js App Router (lib/prisma.ts)
import { PrismaClient } from '@prisma/client';
const prismaClientSingleton = () => new PrismaClient();
declare const globalThis: {
prismaGlobal: ReturnType<typeof prismaClientSingleton>;
} & typeof global;
const prisma = globalThis.prismaGlobal ?? prismaClientSingleton();
export default prisma;
if (process.env.NODE_ENV !== 'production') globalThis.prismaGlobal = prisma;
Environment: DATABASE_URL="postgresql://user:pass@host:5432/db?connection_limit=1&pool_timeout=20"
Usage in Server Action:
import prisma from '@/lib/prisma';
export async function createUser(formData: FormData) {
'use server';
return await prisma.user.create({
data: {
email: formData.get('email') as string,
name: formData.get('name') as string,
},
});
}
Next.js Pages Router / AWS Lambda (lib/prisma.ts)
import { PrismaClient } from '@prisma/client';
declare global {
var prisma: PrismaClient | undefined;
}
const prisma = global.prisma || new PrismaClient();
if (process.env.NODE_ENV !== 'production') global.prisma = prisma;
export default prisma;
Lambda Handler:
import { PrismaClient } from '@prisma/client';
const prisma = new PrismaClient();
export const handler = async (event: any) => {
const users = await prisma.user.findMany();
return { statusCode: 200, body: JSON.stringify(users) };
// Never call prisma.$disconnect() â reuse Lambda container connections
};
With PgBouncer (High Concurrency)
Use when >50
concurrent requests or connection limits still cause issues.
DATABASE_URL="postgresql://user:pass@pgbouncer-host:6543/db?connection_limit=10&pool_timeout=20"
DIRECT_URL="postgresql://user:pass@direct-host:5432/db"
datasource db {
provider = "postgresql"
url = env("DATABASE_URL")
directUrl = env("DIRECT_URL")
}
DATABASE_URL â PgBouncer (queries); DIRECT_URL â database (migrations).
Requirements
MUST: Set connection_limit=1 in DATABASE_URL; use global singleton (never new PrismaClient() in functions); create single lib/prisma.ts imported throughout; add pool_timeout.
SHOULD: Use PgBouncer for high concurrency (>50); monitor production connection count; set limit via URL parameter; reuse Lambda connections.
NEVER: Create new PrismaClient() in routes/handlers; use default pool size in serverless; call $disconnect() in handlers; deploy without limits; split instances across files.
Common Mistakes
| Issue | Wrong | Right |
|---|---|---|
| Connection in Constructor | new PrismaClient({ datasources: { db: { url: ... } } }) |
Set connection_limit=1 in DATABASE_URL |
| Multiple Instances | const prisma = new PrismaClient() inside functions |
Import singleton from lib/prisma |
| Handler Disconnect | await prisma.$disconnect() after query |
Remove disconnect â reuse containers |
| Missing TypeScript Declaration | const prisma = global.prisma || ... |
declare global { var prisma: ... } first |
Validation Checklist
- Environment: DATABASE_URL contains
connection_limit=1andpool_timeout; verified in Vercel dashboard. - Code:
new PrismaClient()appears exactly once inlib/prisma.ts; all other files import from it. - Testing: 10+ concurrent requests to staging; connection count stays â¤10-15; no P1017 errors.
- Monitoring: Production alerts for connection exhaustion and timeout errors.
Platform-Specific Notes
Vercel: Set environment variables in dashboard (
auto-encrypted); connection pooling shared across invocations; consider Vercel Postgres for built-in pooling.
AWS Lambda: Container reuse varies by traffic; cold starts create new instances; use provisioned concurrency for consistency; Lambda layers optimize Prisma binary size.
Cloudflare Workers: Standard PrismaClient unsupported (V8 isolates, not Node.js); use Data Proxy or D1.
Railway/Render: Apply connection_limit=1 pattern; check platform docs for built-in pooling.
Related Skills
Next.js Integration:
- If implementing authenticated data access layers in Next.js, use the securing-data-access-layer skill from nextjs-16 for verifySession() DAL patterns
- If securing server actions with database operations, use the securing-server-actions skill from nextjs-16 for authentication patterns
References
- Next.js patterns:
references/nextjs-patterns.md - Lambda optimization:
references/lambda-patterns.md - PgBouncer setup:
references/pgbouncer-guide.md