opencode-skills-collection 1.0.186 → 1.0.187
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bundled-skills/.antigravity-install-manifest.json +5 -1
- package/bundled-skills/3d-web-experience/SKILL.md +152 -37
- package/bundled-skills/agent-evaluation/SKILL.md +1088 -26
- package/bundled-skills/agent-memory-systems/SKILL.md +1037 -25
- package/bundled-skills/agent-tool-builder/SKILL.md +668 -16
- package/bundled-skills/ai-agents-architect/SKILL.md +271 -31
- package/bundled-skills/ai-product/SKILL.md +716 -26
- package/bundled-skills/ai-wrapper-product/SKILL.md +450 -44
- package/bundled-skills/algolia-search/SKILL.md +867 -15
- package/bundled-skills/autonomous-agents/SKILL.md +1033 -26
- package/bundled-skills/aws-serverless/SKILL.md +1046 -35
- package/bundled-skills/azure-functions/SKILL.md +1318 -19
- package/bundled-skills/browser-automation/SKILL.md +1065 -28
- package/bundled-skills/browser-extension-builder/SKILL.md +159 -32
- package/bundled-skills/bullmq-specialist/SKILL.md +347 -16
- package/bundled-skills/clerk-auth/SKILL.md +796 -15
- package/bundled-skills/computer-use-agents/SKILL.md +1870 -28
- package/bundled-skills/context-window-management/SKILL.md +271 -18
- package/bundled-skills/conversation-memory/SKILL.md +453 -24
- package/bundled-skills/crewai/SKILL.md +252 -46
- package/bundled-skills/discord-bot-architect/SKILL.md +1207 -34
- package/bundled-skills/docs/integrations/jetski-cortex.md +3 -3
- package/bundled-skills/docs/integrations/jetski-gemini-loader/README.md +1 -1
- package/bundled-skills/docs/maintainers/repo-growth-seo.md +3 -3
- package/bundled-skills/docs/maintainers/skills-update-guide.md +1 -1
- package/bundled-skills/docs/users/bundles.md +1 -1
- package/bundled-skills/docs/users/claude-code-skills.md +1 -1
- package/bundled-skills/docs/users/gemini-cli-skills.md +1 -1
- package/bundled-skills/docs/users/getting-started.md +1 -1
- package/bundled-skills/docs/users/kiro-integration.md +1 -1
- package/bundled-skills/docs/users/usage.md +4 -4
- package/bundled-skills/docs/users/visual-guide.md +4 -4
- package/bundled-skills/email-systems/SKILL.md +646 -26
- package/bundled-skills/faf-expert/SKILL.md +221 -0
- package/bundled-skills/faf-wizard/SKILL.md +252 -0
- package/bundled-skills/file-uploads/SKILL.md +212 -11
- package/bundled-skills/firebase/SKILL.md +646 -16
- package/bundled-skills/gcp-cloud-run/SKILL.md +1117 -32
- package/bundled-skills/graphql/SKILL.md +1026 -27
- package/bundled-skills/hubspot-integration/SKILL.md +804 -19
- package/bundled-skills/idea-darwin/SKILL.md +120 -0
- package/bundled-skills/inngest/SKILL.md +431 -16
- package/bundled-skills/interactive-portfolio/SKILL.md +342 -44
- package/bundled-skills/langfuse/SKILL.md +296 -41
- package/bundled-skills/langgraph/SKILL.md +259 -50
- package/bundled-skills/micro-saas-launcher/SKILL.md +343 -44
- package/bundled-skills/neon-postgres/SKILL.md +572 -15
- package/bundled-skills/nextjs-supabase-auth/SKILL.md +269 -21
- package/bundled-skills/notion-template-business/SKILL.md +371 -44
- package/bundled-skills/personal-tool-builder/SKILL.md +537 -44
- package/bundled-skills/plaid-fintech/SKILL.md +825 -19
- package/bundled-skills/prompt-caching/SKILL.md +438 -25
- package/bundled-skills/rag-engineer/SKILL.md +271 -29
- package/bundled-skills/salesforce-development/SKILL.md +912 -19
- package/bundled-skills/satori/SKILL.md +54 -0
- package/bundled-skills/scroll-experience/SKILL.md +381 -44
- package/bundled-skills/segment-cdp/SKILL.md +817 -19
- package/bundled-skills/shopify-apps/SKILL.md +1475 -19
- package/bundled-skills/slack-bot-builder/SKILL.md +1162 -28
- package/bundled-skills/telegram-bot-builder/SKILL.md +152 -37
- package/bundled-skills/telegram-mini-app/SKILL.md +445 -44
- package/bundled-skills/trigger-dev/SKILL.md +916 -27
- package/bundled-skills/twilio-communications/SKILL.md +1310 -28
- package/bundled-skills/upstash-qstash/SKILL.md +898 -27
- package/bundled-skills/vercel-deployment/SKILL.md +637 -39
- package/bundled-skills/viral-generator-builder/SKILL.md +132 -37
- package/bundled-skills/voice-agents/SKILL.md +937 -27
- package/bundled-skills/voice-ai-development/SKILL.md +375 -46
- package/bundled-skills/workflow-automation/SKILL.md +982 -29
- package/bundled-skills/zapier-make-patterns/SKILL.md +772 -27
- package/package.json +1 -1
|
@@ -1,13 +1,16 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: neon-postgres
|
|
3
|
-
description:
|
|
3
|
+
description: Expert patterns for Neon serverless Postgres, branching, connection
|
|
4
|
+
pooling, and Prisma/Drizzle integration
|
|
4
5
|
risk: safe
|
|
5
|
-
source:
|
|
6
|
-
date_added:
|
|
6
|
+
source: vibeship-spawner-skills (Apache 2.0)
|
|
7
|
+
date_added: 2026-02-27
|
|
7
8
|
---
|
|
8
9
|
|
|
9
10
|
# Neon Postgres
|
|
10
11
|
|
|
12
|
+
Expert patterns for Neon serverless Postgres, branching, connection pooling, and Prisma/Drizzle integration
|
|
13
|
+
|
|
11
14
|
## Patterns
|
|
12
15
|
|
|
13
16
|
### Prisma with Neon Connection
|
|
@@ -21,6 +24,65 @@ Use two connection strings:
|
|
|
21
24
|
The pooled connection uses PgBouncer for up to 10K connections.
|
|
22
25
|
Direct connection required for migrations (DDL operations).
|
|
23
26
|
|
|
27
|
+
### Code_example
|
|
28
|
+
|
|
29
|
+
# .env
|
|
30
|
+
# Pooled connection for application queries
|
|
31
|
+
DATABASE_URL="postgres://user:password@ep-xxx-pooler.us-east-2.aws.neon.tech/neondb?sslmode=require"
|
|
32
|
+
# Direct connection for migrations
|
|
33
|
+
DIRECT_URL="postgres://user:password@ep-xxx.us-east-2.aws.neon.tech/neondb?sslmode=require"
|
|
34
|
+
|
|
35
|
+
// prisma/schema.prisma
|
|
36
|
+
generator client {
|
|
37
|
+
provider = "prisma-client-js"
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
datasource db {
|
|
41
|
+
provider = "postgresql"
|
|
42
|
+
url = env("DATABASE_URL")
|
|
43
|
+
directUrl = env("DIRECT_URL")
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
model User {
|
|
47
|
+
id String @id @default(cuid())
|
|
48
|
+
email String @unique
|
|
49
|
+
name String?
|
|
50
|
+
createdAt DateTime @default(now())
|
|
51
|
+
updatedAt DateTime @updatedAt
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
// lib/prisma.ts
|
|
55
|
+
import { PrismaClient } from '@prisma/client';
|
|
56
|
+
|
|
57
|
+
const globalForPrisma = globalThis as unknown as {
|
|
58
|
+
prisma: PrismaClient | undefined;
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
export const prisma = globalForPrisma.prisma ?? new PrismaClient({
|
|
62
|
+
log: process.env.NODE_ENV === 'development'
|
|
63
|
+
? ['query', 'error', 'warn']
|
|
64
|
+
: ['error'],
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
if (process.env.NODE_ENV !== 'production') {
|
|
68
|
+
globalForPrisma.prisma = prisma;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
// Run migrations
|
|
72
|
+
// Uses DIRECT_URL automatically
|
|
73
|
+
npx prisma migrate dev
|
|
74
|
+
npx prisma migrate deploy
|
|
75
|
+
|
|
76
|
+
### Anti_patterns
|
|
77
|
+
|
|
78
|
+
- Pattern: Using pooled connection for migrations | Why: DDL operations fail through PgBouncer | Fix: Set directUrl in schema.prisma
|
|
79
|
+
- Pattern: Not using connection pooling | Why: Serverless functions exhaust connection limits | Fix: Use -pooler endpoint in DATABASE_URL
|
|
80
|
+
|
|
81
|
+
### References
|
|
82
|
+
|
|
83
|
+
- https://neon.com/docs/guides/prisma
|
|
84
|
+
- https://www.prisma.io/docs/orm/overview/databases/neon
|
|
85
|
+
|
|
24
86
|
### Drizzle with Neon Serverless Driver
|
|
25
87
|
|
|
26
88
|
Use Drizzle ORM with Neon's serverless HTTP driver for
|
|
@@ -30,6 +92,80 @@ Two driver options:
|
|
|
30
92
|
- neon-http: Single queries over HTTP (fastest for one-off queries)
|
|
31
93
|
- neon-serverless: WebSocket for transactions and sessions
|
|
32
94
|
|
|
95
|
+
### Code_example
|
|
96
|
+
|
|
97
|
+
# Install dependencies
|
|
98
|
+
npm install drizzle-orm @neondatabase/serverless
|
|
99
|
+
npm install -D drizzle-kit
|
|
100
|
+
|
|
101
|
+
// lib/db/schema.ts
|
|
102
|
+
import { pgTable, serial, text, timestamp } from 'drizzle-orm/pg-core';
|
|
103
|
+
|
|
104
|
+
export const users = pgTable('users', {
|
|
105
|
+
id: serial('id').primaryKey(),
|
|
106
|
+
email: text('email').notNull().unique(),
|
|
107
|
+
name: text('name'),
|
|
108
|
+
createdAt: timestamp('created_at').defaultNow().notNull(),
|
|
109
|
+
updatedAt: timestamp('updated_at').defaultNow().notNull(),
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
// lib/db/index.ts (for serverless - HTTP driver)
|
|
113
|
+
import { neon } from '@neondatabase/serverless';
|
|
114
|
+
import { drizzle } from 'drizzle-orm/neon-http';
|
|
115
|
+
import * as schema from './schema';
|
|
116
|
+
|
|
117
|
+
const sql = neon(process.env.DATABASE_URL!);
|
|
118
|
+
export const db = drizzle(sql, { schema });
|
|
119
|
+
|
|
120
|
+
// Usage in API route
|
|
121
|
+
import { db } from '@/lib/db';
|
|
122
|
+
import { users } from '@/lib/db/schema';
|
|
123
|
+
|
|
124
|
+
export async function GET() {
|
|
125
|
+
const allUsers = await db.select().from(users);
|
|
126
|
+
return Response.json(allUsers);
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
// lib/db/index.ts (for WebSocket - transactions)
|
|
130
|
+
import { Pool } from '@neondatabase/serverless';
|
|
131
|
+
import { drizzle } from 'drizzle-orm/neon-serverless';
|
|
132
|
+
import * as schema from './schema';
|
|
133
|
+
|
|
134
|
+
const pool = new Pool({ connectionString: process.env.DATABASE_URL });
|
|
135
|
+
export const db = drizzle(pool, { schema });
|
|
136
|
+
|
|
137
|
+
// With transactions
|
|
138
|
+
await db.transaction(async (tx) => {
|
|
139
|
+
await tx.insert(users).values({ email: 'test@example.com' });
|
|
140
|
+
await tx.update(users).set({ name: 'Updated' });
|
|
141
|
+
});
|
|
142
|
+
|
|
143
|
+
// drizzle.config.ts
|
|
144
|
+
import { defineConfig } from 'drizzle-kit';
|
|
145
|
+
|
|
146
|
+
export default defineConfig({
|
|
147
|
+
schema: './lib/db/schema.ts',
|
|
148
|
+
out: './drizzle',
|
|
149
|
+
dialect: 'postgresql',
|
|
150
|
+
dbCredentials: {
|
|
151
|
+
url: process.env.DATABASE_URL!,
|
|
152
|
+
},
|
|
153
|
+
});
|
|
154
|
+
|
|
155
|
+
// Run migrations
|
|
156
|
+
npx drizzle-kit generate
|
|
157
|
+
npx drizzle-kit migrate
|
|
158
|
+
|
|
159
|
+
### Anti_patterns
|
|
160
|
+
|
|
161
|
+
- Pattern: Using pg driver in serverless | Why: TCP connections don't work in all edge environments | Fix: Use @neondatabase/serverless driver
|
|
162
|
+
- Pattern: HTTP driver for transactions | Why: HTTP driver doesn't support transactions | Fix: Use WebSocket driver (Pool) for transactions
|
|
163
|
+
|
|
164
|
+
### References
|
|
165
|
+
|
|
166
|
+
- https://neon.com/docs/guides/drizzle
|
|
167
|
+
- https://orm.drizzle.team/docs/connect-neon
|
|
168
|
+
|
|
33
169
|
### Connection Pooling with PgBouncer
|
|
34
170
|
|
|
35
171
|
Neon provides built-in connection pooling via PgBouncer.
|
|
@@ -41,18 +177,439 @@ Key limits:
|
|
|
41
177
|
|
|
42
178
|
Use pooled endpoint for application, direct for migrations.
|
|
43
179
|
|
|
44
|
-
|
|
180
|
+
### Code_example
|
|
181
|
+
|
|
182
|
+
# Connection string formats
|
|
183
|
+
|
|
184
|
+
# Pooled connection (for application)
|
|
185
|
+
# Note: -pooler in hostname
|
|
186
|
+
postgres://user:pass@ep-cool-name-pooler.us-east-2.aws.neon.tech/neondb
|
|
187
|
+
|
|
188
|
+
# Direct connection (for migrations)
|
|
189
|
+
# Note: No -pooler
|
|
190
|
+
postgres://user:pass@ep-cool-name.us-east-2.aws.neon.tech/neondb
|
|
191
|
+
|
|
192
|
+
// Prisma with pooling
|
|
193
|
+
// prisma/schema.prisma
|
|
194
|
+
datasource db {
|
|
195
|
+
provider = "postgresql"
|
|
196
|
+
url = env("DATABASE_URL") // Pooled
|
|
197
|
+
directUrl = env("DIRECT_URL") // Direct
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
// Connection pool settings for high-traffic
|
|
201
|
+
// lib/prisma.ts
|
|
202
|
+
import { PrismaClient } from '@prisma/client';
|
|
203
|
+
|
|
204
|
+
export const prisma = new PrismaClient({
|
|
205
|
+
datasources: {
|
|
206
|
+
db: {
|
|
207
|
+
url: process.env.DATABASE_URL,
|
|
208
|
+
},
|
|
209
|
+
},
|
|
210
|
+
// Connection pool settings
|
|
211
|
+
// Adjust based on compute size
|
|
212
|
+
});
|
|
213
|
+
|
|
214
|
+
// For Drizzle with connection pool
|
|
215
|
+
import { Pool } from '@neondatabase/serverless';
|
|
216
|
+
|
|
217
|
+
const pool = new Pool({
|
|
218
|
+
connectionString: process.env.DATABASE_URL,
|
|
219
|
+
max: 10, // Max connections in local pool
|
|
220
|
+
idleTimeoutMillis: 30000,
|
|
221
|
+
connectionTimeoutMillis: 10000,
|
|
222
|
+
});
|
|
223
|
+
|
|
224
|
+
// Compute size connection limits
|
|
225
|
+
// 0.25 CU: 112 connections (105 available after reserved)
|
|
226
|
+
// 0.5 CU: 225 connections
|
|
227
|
+
// 1 CU: 450 connections
|
|
228
|
+
// 2 CU: 901 connections
|
|
229
|
+
// 4 CU: 1802 connections
|
|
230
|
+
// 8 CU: 3604 connections
|
|
231
|
+
|
|
232
|
+
### Anti_patterns
|
|
233
|
+
|
|
234
|
+
- Pattern: Opening new connection per request | Why: Exhausts connection limits quickly | Fix: Use connection pooling, reuse connections
|
|
235
|
+
- Pattern: High max pool size in serverless | Why: Many function instances = many pools = many connections | Fix: Keep local pool size low (5-10), rely on PgBouncer
|
|
236
|
+
|
|
237
|
+
### References
|
|
238
|
+
|
|
239
|
+
- https://neon.com/docs/connect/connection-pooling
|
|
240
|
+
|
|
241
|
+
### Database Branching for Development
|
|
242
|
+
|
|
243
|
+
Create instant copies of your database for development,
|
|
244
|
+
testing, and preview environments.
|
|
245
|
+
|
|
246
|
+
Branches share underlying storage (copy-on-write),
|
|
247
|
+
making them instant and cost-effective.
|
|
248
|
+
|
|
249
|
+
### Code_example
|
|
250
|
+
|
|
251
|
+
# Create branch via Neon CLI
|
|
252
|
+
neon branches create --name feature/new-feature --parent main
|
|
253
|
+
|
|
254
|
+
# Create branch from specific point in time
|
|
255
|
+
neon branches create --name debug/yesterday \
|
|
256
|
+
--parent main \
|
|
257
|
+
--timestamp "2024-01-15T10:00:00Z"
|
|
258
|
+
|
|
259
|
+
# List branches
|
|
260
|
+
neon branches list
|
|
261
|
+
|
|
262
|
+
# Get connection string for branch
|
|
263
|
+
neon connection-string feature/new-feature
|
|
264
|
+
|
|
265
|
+
# Delete branch when done
|
|
266
|
+
neon branches delete feature/new-feature
|
|
267
|
+
|
|
268
|
+
// In CI/CD (GitHub Actions)
|
|
269
|
+
// .github/workflows/preview.yml
|
|
270
|
+
name: Preview Environment
|
|
271
|
+
on:
|
|
272
|
+
pull_request:
|
|
273
|
+
types: [opened, synchronize]
|
|
274
|
+
|
|
275
|
+
jobs:
|
|
276
|
+
create-branch:
|
|
277
|
+
runs-on: ubuntu-latest
|
|
278
|
+
steps:
|
|
279
|
+
- uses: neondatabase/create-branch-action@v5
|
|
280
|
+
id: create-branch
|
|
281
|
+
with:
|
|
282
|
+
project_id: ${{ secrets.NEON_PROJECT_ID }}
|
|
283
|
+
branch_name: preview/pr-${{ github.event.pull_request.number }}
|
|
284
|
+
api_key: ${{ secrets.NEON_API_KEY }}
|
|
285
|
+
username: ${{ secrets.NEON_ROLE_NAME }}
|
|
286
|
+
|
|
287
|
+
- name: Run migrations
|
|
288
|
+
env:
|
|
289
|
+
DATABASE_URL: ${{ steps.create-branch.outputs.db_url_with_pooler }}
|
|
290
|
+
run: npx prisma migrate deploy
|
|
291
|
+
|
|
292
|
+
- name: Deploy to Vercel
|
|
293
|
+
env:
|
|
294
|
+
DATABASE_URL: ${{ steps.create-branch.outputs.db_url_with_pooler }}
|
|
295
|
+
run: vercel deploy --prebuilt
|
|
296
|
+
|
|
297
|
+
// Cleanup on PR close
|
|
298
|
+
on:
|
|
299
|
+
pull_request:
|
|
300
|
+
types: [closed]
|
|
301
|
+
|
|
302
|
+
jobs:
|
|
303
|
+
delete-branch:
|
|
304
|
+
runs-on: ubuntu-latest
|
|
305
|
+
steps:
|
|
306
|
+
- uses: neondatabase/delete-branch-action@v3
|
|
307
|
+
with:
|
|
308
|
+
project_id: ${{ secrets.NEON_PROJECT_ID }}
|
|
309
|
+
branch: preview/pr-${{ github.event.pull_request.number }}
|
|
310
|
+
api_key: ${{ secrets.NEON_API_KEY }}
|
|
311
|
+
|
|
312
|
+
### Anti_patterns
|
|
313
|
+
|
|
314
|
+
- Pattern: Sharing production database for development | Why: Risk of data corruption, no isolation | Fix: Create development branches from production
|
|
315
|
+
- Pattern: Not cleaning up old branches | Why: Accumulates storage and clutter | Fix: Auto-delete branches on PR close
|
|
316
|
+
|
|
317
|
+
### References
|
|
318
|
+
|
|
319
|
+
- https://neon.com/blog/branching-with-preview-environments
|
|
320
|
+
- https://github.com/neondatabase/create-branch-action
|
|
321
|
+
|
|
322
|
+
### Vercel Preview Environment Integration
|
|
323
|
+
|
|
324
|
+
Automatically create database branches for Vercel preview
|
|
325
|
+
deployments. Each PR gets its own isolated database.
|
|
326
|
+
|
|
327
|
+
Two integration options:
|
|
328
|
+
- Vercel-Managed: Billing in Vercel, auto-setup
|
|
329
|
+
- Neon-Managed: Billing in Neon, more control
|
|
330
|
+
|
|
331
|
+
### Code_example
|
|
332
|
+
|
|
333
|
+
# Vercel-Managed Integration
|
|
334
|
+
# 1. Go to Vercel Dashboard > Storage > Create Database
|
|
335
|
+
# 2. Select Neon Postgres
|
|
336
|
+
# 3. Enable "Create a branch for each preview deployment"
|
|
337
|
+
# 4. Environment variables automatically injected
|
|
338
|
+
|
|
339
|
+
# Neon-Managed Integration
|
|
340
|
+
# 1. Install from Neon Dashboard > Integrations > Vercel
|
|
341
|
+
# 2. Select Vercel project to connect
|
|
342
|
+
# 3. Enable "Create a branch for each preview deployment"
|
|
343
|
+
# 4. Optionally enable auto-delete on branch delete
|
|
344
|
+
|
|
345
|
+
// vercel.json - Add migration to build
|
|
346
|
+
{
|
|
347
|
+
"buildCommand": "prisma migrate deploy && next build",
|
|
348
|
+
"framework": "nextjs"
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
// Or in package.json
|
|
352
|
+
{
|
|
353
|
+
"scripts": {
|
|
354
|
+
"vercel-build": "prisma generate && prisma migrate deploy && next build"
|
|
355
|
+
}
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
// Environment variables injected by integration
|
|
359
|
+
// DATABASE_URL - Pooled connection for preview branch
|
|
360
|
+
// DATABASE_URL_UNPOOLED - Direct connection for migrations
|
|
361
|
+
// PGHOST, PGUSER, PGDATABASE, PGPASSWORD - Individual vars
|
|
362
|
+
|
|
363
|
+
// Prisma schema for Vercel integration
|
|
364
|
+
datasource db {
|
|
365
|
+
provider = "postgresql"
|
|
366
|
+
url = env("DATABASE_URL")
|
|
367
|
+
directUrl = env("DATABASE_URL_UNPOOLED") // Vercel variable
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
// For Drizzle in Next.js on Vercel
|
|
371
|
+
import { neon } from '@neondatabase/serverless';
|
|
372
|
+
import { drizzle } from 'drizzle-orm/neon-http';
|
|
373
|
+
|
|
374
|
+
// Use pooled URL for queries
|
|
375
|
+
const sql = neon(process.env.DATABASE_URL!);
|
|
376
|
+
export const db = drizzle(sql);
|
|
377
|
+
|
|
378
|
+
### Anti_patterns
|
|
379
|
+
|
|
380
|
+
- Pattern: Same database for all previews | Why: Previews interfere with each other | Fix: Enable branch-per-preview in integration
|
|
381
|
+
- Pattern: Not running migrations on preview | Why: Schema mismatch between code and database | Fix: Add migrate command to build step
|
|
382
|
+
|
|
383
|
+
### References
|
|
384
|
+
|
|
385
|
+
- https://neon.com/docs/guides/vercel-managed-integration
|
|
386
|
+
- https://neon.com/docs/guides/neon-managed-vercel-integration
|
|
387
|
+
|
|
388
|
+
### Autoscaling and Cold Start Management
|
|
389
|
+
|
|
390
|
+
Neon autoscales compute resources and scales to zero.
|
|
45
391
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
392
|
+
Cold start latency: 500ms - few seconds when waking from idle.
|
|
393
|
+
Production recommendation: Disable scale-to-zero, set minimum compute.
|
|
394
|
+
|
|
395
|
+
### Code_example
|
|
396
|
+
|
|
397
|
+
# Neon Console settings for production
|
|
398
|
+
# Project Settings > Compute > Default compute size
|
|
399
|
+
# - Set minimum to 0.5 CU or higher
|
|
400
|
+
# - Disable "Suspend compute after inactivity"
|
|
401
|
+
|
|
402
|
+
// Handle cold starts in application
|
|
403
|
+
// lib/db-with-retry.ts
|
|
404
|
+
import { prisma } from './prisma';
|
|
405
|
+
|
|
406
|
+
const MAX_RETRIES = 3;
|
|
407
|
+
const RETRY_DELAY = 1000;
|
|
408
|
+
|
|
409
|
+
export async function queryWithRetry<T>(
|
|
410
|
+
query: () => Promise<T>
|
|
411
|
+
): Promise<T> {
|
|
412
|
+
let lastError: Error | undefined;
|
|
413
|
+
|
|
414
|
+
for (let attempt = 1; attempt <= MAX_RETRIES; attempt++) {
|
|
415
|
+
try {
|
|
416
|
+
return await query();
|
|
417
|
+
} catch (error) {
|
|
418
|
+
lastError = error as Error;
|
|
419
|
+
|
|
420
|
+
// Retry on connection errors (cold start)
|
|
421
|
+
if (error.code === 'P1001' || error.code === 'P1002') {
|
|
422
|
+
console.log(`Retry attempt ${attempt}/${MAX_RETRIES}`);
|
|
423
|
+
await new Promise(r => setTimeout(r, RETRY_DELAY * attempt));
|
|
424
|
+
continue;
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
throw error;
|
|
428
|
+
}
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
throw lastError;
|
|
432
|
+
}
|
|
433
|
+
|
|
434
|
+
// Usage
|
|
435
|
+
const users = await queryWithRetry(() =>
|
|
436
|
+
prisma.user.findMany()
|
|
437
|
+
);
|
|
438
|
+
|
|
439
|
+
// Reduce cold start latency with SSL direct negotiation
|
|
440
|
+
# PostgreSQL 17+ connection string
|
|
441
|
+
postgres://user:pass@ep-xxx-pooler.aws.neon.tech/db?sslmode=require&sslnegotiation=direct
|
|
442
|
+
|
|
443
|
+
// Keep-alive for long-running apps
|
|
444
|
+
// lib/db-keepalive.ts
|
|
445
|
+
import { prisma } from './prisma';
|
|
446
|
+
|
|
447
|
+
// Ping database every 4 minutes to prevent suspend
|
|
448
|
+
const KEEPALIVE_INTERVAL = 4 * 60 * 1000;
|
|
449
|
+
|
|
450
|
+
if (process.env.NEON_KEEPALIVE === 'true') {
|
|
451
|
+
setInterval(async () => {
|
|
452
|
+
try {
|
|
453
|
+
await prisma.$queryRaw`SELECT 1`;
|
|
454
|
+
} catch (error) {
|
|
455
|
+
console.error('Keepalive failed:', error);
|
|
456
|
+
}
|
|
457
|
+
}, KEEPALIVE_INTERVAL);
|
|
458
|
+
}
|
|
459
|
+
|
|
460
|
+
// Compute sizing recommendations
|
|
461
|
+
// Development: 0.25 CU, scale-to-zero enabled
|
|
462
|
+
// Staging: 0.5 CU, scale-to-zero enabled
|
|
463
|
+
// Production: 1+ CU, scale-to-zero DISABLED
|
|
464
|
+
// High-traffic: 2-4 CU minimum, autoscaling enabled
|
|
465
|
+
|
|
466
|
+
### Anti_patterns
|
|
467
|
+
|
|
468
|
+
- Pattern: Scale-to-zero in production | Why: Cold starts add 500ms+ latency to first request | Fix: Disable scale-to-zero for production branch
|
|
469
|
+
- Pattern: No retry logic for cold starts | Why: First connection after idle may timeout | Fix: Add retry with exponential backoff
|
|
470
|
+
|
|
471
|
+
### References
|
|
472
|
+
|
|
473
|
+
- https://neon.com/blog/scaling-serverless-postgres
|
|
474
|
+
- https://neon.com/docs/connect/connection-latency
|
|
475
|
+
|
|
476
|
+
## Sharp Edges
|
|
477
|
+
|
|
478
|
+
### Cold Start Latency After Scale-to-Zero
|
|
479
|
+
|
|
480
|
+
Severity: HIGH
|
|
481
|
+
|
|
482
|
+
### Using Pooled Connection for Migrations
|
|
483
|
+
|
|
484
|
+
Severity: HIGH
|
|
485
|
+
|
|
486
|
+
### Connection Pool Exhaustion in Serverless
|
|
487
|
+
|
|
488
|
+
Severity: HIGH
|
|
489
|
+
|
|
490
|
+
### PgBouncer Feature Limitations
|
|
491
|
+
|
|
492
|
+
Severity: MEDIUM
|
|
493
|
+
|
|
494
|
+
### Branch Storage Accumulation
|
|
495
|
+
|
|
496
|
+
Severity: MEDIUM
|
|
497
|
+
|
|
498
|
+
### Reserved Connections Reduce Available Pool
|
|
499
|
+
|
|
500
|
+
Severity: LOW
|
|
501
|
+
|
|
502
|
+
### HTTP Driver Doesn't Support Transactions
|
|
503
|
+
|
|
504
|
+
Severity: MEDIUM
|
|
505
|
+
|
|
506
|
+
### Deleting Parent Branch Affects Children
|
|
507
|
+
|
|
508
|
+
Severity: HIGH
|
|
509
|
+
|
|
510
|
+
### Schema Drift Between Branches
|
|
511
|
+
|
|
512
|
+
Severity: MEDIUM
|
|
513
|
+
|
|
514
|
+
## Validation Checks
|
|
515
|
+
|
|
516
|
+
### Direct Database URL in Client Code
|
|
517
|
+
|
|
518
|
+
Severity: ERROR
|
|
519
|
+
|
|
520
|
+
Direct database URLs should never be exposed to client
|
|
521
|
+
|
|
522
|
+
Message: Direct URL exposed to client. Only pooled URLs for server-side use.
|
|
523
|
+
|
|
524
|
+
### Hardcoded Database Connection String
|
|
525
|
+
|
|
526
|
+
Severity: ERROR
|
|
527
|
+
|
|
528
|
+
Connection strings should use environment variables
|
|
529
|
+
|
|
530
|
+
Message: Hardcoded connection string. Use environment variables.
|
|
531
|
+
|
|
532
|
+
### Missing SSL Mode in Connection String
|
|
533
|
+
|
|
534
|
+
Severity: WARNING
|
|
535
|
+
|
|
536
|
+
Neon requires SSL connections
|
|
537
|
+
|
|
538
|
+
Message: Missing sslmode=require. Add to connection string.
|
|
539
|
+
|
|
540
|
+
### Prisma Missing directUrl for Migrations
|
|
541
|
+
|
|
542
|
+
Severity: ERROR
|
|
543
|
+
|
|
544
|
+
Prisma needs directUrl for migrations through PgBouncer
|
|
545
|
+
|
|
546
|
+
Message: Using pooled URL without directUrl. Migrations will fail.
|
|
547
|
+
|
|
548
|
+
### Prisma directUrl Points to Pooler
|
|
549
|
+
|
|
550
|
+
Severity: ERROR
|
|
551
|
+
|
|
552
|
+
directUrl should be non-pooled connection
|
|
553
|
+
|
|
554
|
+
Message: directUrl points to pooler. Use non-pooled endpoint for migrations.
|
|
555
|
+
|
|
556
|
+
### High Pool Size in Serverless Function
|
|
557
|
+
|
|
558
|
+
Severity: WARNING
|
|
559
|
+
|
|
560
|
+
High pool sizes exhaust connections with many function instances
|
|
561
|
+
|
|
562
|
+
Message: Pool size too high for serverless. Use max: 5-10.
|
|
563
|
+
|
|
564
|
+
### Creating New Client Per Request
|
|
565
|
+
|
|
566
|
+
Severity: WARNING
|
|
567
|
+
|
|
568
|
+
Creating new clients per request wastes connections
|
|
569
|
+
|
|
570
|
+
Message: Creating client per request. Use connection pool or neon() driver.
|
|
571
|
+
|
|
572
|
+
### Branch Creation Without Cleanup Strategy
|
|
573
|
+
|
|
574
|
+
Severity: WARNING
|
|
575
|
+
|
|
576
|
+
Branches should have cleanup automation
|
|
577
|
+
|
|
578
|
+
Message: Creating branch without cleanup. Add delete-branch-action to PR close.
|
|
579
|
+
|
|
580
|
+
### Scale-to-Zero Enabled on Production
|
|
581
|
+
|
|
582
|
+
Severity: WARNING
|
|
583
|
+
|
|
584
|
+
Scale-to-zero adds latency in production
|
|
585
|
+
|
|
586
|
+
Message: Scale-to-zero on production. Disable for low-latency.
|
|
587
|
+
|
|
588
|
+
### HTTP Driver Used for Transactions
|
|
589
|
+
|
|
590
|
+
Severity: ERROR
|
|
591
|
+
|
|
592
|
+
neon() HTTP driver doesn't support transactions
|
|
593
|
+
|
|
594
|
+
Message: HTTP driver with transaction. Use Pool from @neondatabase/serverless.
|
|
595
|
+
|
|
596
|
+
## Collaboration
|
|
597
|
+
|
|
598
|
+
### Delegation Triggers
|
|
599
|
+
|
|
600
|
+
- user needs authentication -> clerk-auth (User table with clerkId column)
|
|
601
|
+
- user needs caching -> redis-specialist (Query caching, session storage)
|
|
602
|
+
- user needs search -> algolia-search (Full-text search beyond Postgres capabilities)
|
|
603
|
+
- user needs analytics -> segment-cdp (Track database events, user actions)
|
|
604
|
+
- user needs deployment -> vercel-deployment (Environment variables, preview databases)
|
|
56
605
|
|
|
57
606
|
## When to Use
|
|
58
|
-
|
|
607
|
+
|
|
608
|
+
- User mentions or implies: neon database
|
|
609
|
+
- User mentions or implies: serverless postgres
|
|
610
|
+
- User mentions or implies: database branching
|
|
611
|
+
- User mentions or implies: neon postgres
|
|
612
|
+
- User mentions or implies: postgres serverless
|
|
613
|
+
- User mentions or implies: connection pooling
|
|
614
|
+
- User mentions or implies: preview environments
|
|
615
|
+
- User mentions or implies: database per preview
|