Add Claude commands, remote-exec script, and skills
- commands/remote.md for remote execution - remote-exec.sh script - skills: claudeception, kubernetes-latest-tag-image-pull, react-hooks-order-early-return
This commit is contained in:
parent
09631b3530
commit
fde360dbdc
44 changed files with 3053 additions and 0 deletions
|
|
@ -0,0 +1,161 @@
|
|||
---
|
||||
name: prisma-connection-pool-exhaustion
|
||||
description: |
|
||||
Fix Prisma "Too many connections" and connection pool exhaustion errors in
|
||||
serverless environments (Vercel, AWS Lambda, Netlify). Use when: (1) Error
|
||||
"P2024: Timed out fetching a new connection from the pool", (2) PostgreSQL
|
||||
"too many connections for role", (3) Database works locally but fails in
|
||||
production serverless, (4) Intermittent database timeouts under load.
|
||||
author: Claude Code
|
||||
version: 1.0.0
|
||||
date: 2024-02-20
|
||||
---
|
||||
|
||||
# Prisma Connection Pool Exhaustion in Serverless
|
||||
|
||||
## Problem
|
||||
|
||||
Serverless functions create a new Prisma client instance on each cold start. Each
|
||||
instance opens multiple database connections (default: 5 per instance). With many
|
||||
concurrent requests, this quickly exhausts the database's connection limit (often
|
||||
20-100 for managed databases).
|
||||
|
||||
## Context / Trigger Conditions
|
||||
|
||||
This skill applies when you see:
|
||||
|
||||
- `P2024: Timed out fetching a new connection from the connection pool`
|
||||
- PostgreSQL: `FATAL: too many connections for role "username"`
|
||||
- MySQL: `Too many connections`
|
||||
- Works fine locally with `npm run dev` but fails in production
|
||||
- Errors appear during traffic spikes, then resolve
|
||||
- Database dashboard shows connections at or near limit
|
||||
|
||||
Environment indicators:
|
||||
- Deploying to Vercel, AWS Lambda, Netlify Functions, or similar
|
||||
- Using Prisma with PostgreSQL, MySQL, or another connection-based database
|
||||
- Database is managed (PlanetScale, Supabase, Neon, RDS, etc.)
|
||||
|
||||
## Solution
|
||||
|
||||
### Step 1: Use Connection Pooling Service
|
||||
|
||||
The recommended solution is to use a connection pooler like PgBouncer or Prisma
|
||||
Accelerate, which sits between your serverless functions and the database.
|
||||
|
||||
**For Supabase:**
|
||||
```
|
||||
# .env
|
||||
# Use the pooled connection string (port 6543, not 5432)
|
||||
DATABASE_URL="postgresql://user:pass@db.xxx.supabase.co:6543/postgres?pgbouncer=true"
|
||||
```
|
||||
|
||||
**For Neon:**
|
||||
```
|
||||
# .env
|
||||
DATABASE_URL="postgresql://user:pass@ep-xxx.us-east-2.aws.neon.tech/dbname?sslmode=require"
|
||||
# Neon has built-in pooling
|
||||
```
|
||||
|
||||
**For Prisma Accelerate:**
|
||||
```bash
|
||||
npx prisma generate --accelerate
|
||||
```
|
||||
|
||||
### Step 2: Configure Prisma Connection Limits
|
||||
|
||||
In your `schema.prisma`:
|
||||
|
||||
```prisma
|
||||
datasource db {
|
||||
provider = "postgresql"
|
||||
url = env("DATABASE_URL")
|
||||
// Limit connections per Prisma instance
|
||||
relationMode = "prisma"
|
||||
}
|
||||
```
|
||||
|
||||
In your connection URL or Prisma client:
|
||||
|
||||
```typescript
|
||||
// lib/prisma.ts
|
||||
import { PrismaClient } from '@prisma/client'
|
||||
|
||||
const globalForPrisma = global as unknown as { prisma: PrismaClient }
|
||||
|
||||
export const prisma = globalForPrisma.prisma || new PrismaClient({
|
||||
datasources: {
|
||||
db: {
|
||||
url: process.env.DATABASE_URL + '?connection_limit=1'
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
if (process.env.NODE_ENV !== 'production') globalForPrisma.prisma = prisma
|
||||
```
|
||||
|
||||
### Step 3: Singleton Pattern (Development)
|
||||
|
||||
Prevent hot-reload from creating new clients:
|
||||
|
||||
```typescript
|
||||
// lib/prisma.ts
|
||||
import { PrismaClient } from '@prisma/client'
|
||||
|
||||
const globalForPrisma = globalThis as unknown as {
|
||||
prisma: PrismaClient | undefined
|
||||
}
|
||||
|
||||
export const prisma = globalForPrisma.prisma ?? new PrismaClient()
|
||||
|
||||
if (process.env.NODE_ENV !== 'production') globalForPrisma.prisma = prisma
|
||||
```
|
||||
|
||||
### Step 4: URL Parameters
|
||||
|
||||
Add these to your connection string:
|
||||
|
||||
```
|
||||
?connection_limit=1&pool_timeout=20&connect_timeout=10
|
||||
```
|
||||
|
||||
- `connection_limit=1`: One connection per serverless instance
|
||||
- `pool_timeout=20`: Wait up to 20s for available connection
|
||||
- `connect_timeout=10`: Fail fast if can't connect in 10s
|
||||
|
||||
## Verification
|
||||
|
||||
After applying fixes:
|
||||
|
||||
1. Deploy to production
|
||||
2. Run a load test: `npx autocannon -c 100 -d 30 https://your-app.com/api/test`
|
||||
3. Check database dashboard—connections should stay within limits
|
||||
4. No more P2024 errors in logs
|
||||
|
||||
## Example
|
||||
|
||||
**Before** (error under load):
|
||||
```
|
||||
[ERROR] PrismaClientKnownRequestError:
|
||||
Invalid `prisma.user.findMany()` invocation:
|
||||
Timed out fetching a new connection from the connection pool.
|
||||
```
|
||||
|
||||
**After** (with connection pooling):
|
||||
```
|
||||
# Using Supabase pooler URL
|
||||
DATABASE_URL="postgresql://...@db.xxx.supabase.co:6543/postgres?pgbouncer=true&connection_limit=1"
|
||||
```
|
||||
|
||||
Database connections stable at 10-15 even under heavy load.
|
||||
|
||||
## Notes
|
||||
|
||||
- Different managed databases have different pooling solutions—check your provider's docs
|
||||
- PlanetScale (MySQL) uses a different architecture and doesn't have this issue
|
||||
- `connection_limit=1` is aggressive; start there and increase if you see latency
|
||||
- The singleton pattern only helps in development; in production serverless, each
|
||||
instance is isolated
|
||||
- If using Prisma with Next.js API routes, each route invocation may be a separate
|
||||
serverless function
|
||||
- Consider Prisma Accelerate for built-in caching + pooling: https://www.prisma.io/accelerate
|
||||
Loading…
Add table
Add a link
Reference in a new issue