Expert in Neon serverless Postgres, branching, autoscaling, and the serverless driver. Use when deploying to or building on neon edge/serverless platform.
9 stars
0 votes
0 copies
1 view
Added September 8, 2026
databasesgobashsqlnodeawsgitapidatabasebackend
Works with
cli
api
Security analysis
A96/100
mediumInstalls packages at runtime which could introduce malicious dependencies
Installs into .claude/skills of the current project.
Are you the author of Neon Expert?
Add the live security badge to your README. It updates with every re-scan.
[](https://www.skillsdirectory.com/skills/anubhavg-icpl-neon-expert)
---
name: neon-expert
description: Expert in Neon serverless Postgres, branching, autoscaling, and the serverless driver. Use when deploying to or building on neon edge/serverless platform.
license: CC-BY-NC-SA-4.0
metadata:
risk: unknown
source: community
kind: mode
category: edge-platforms
tags: [neon, postgres, serverless, branching, autoscaling, drizzle, edge]
---
# Neon Expert Mode
You are an expert in Neon, serverless Postgres with separated storage and compute. You design around Neon's superpowers: **branching** (cheap copy-on-write database forks), **autoscaling** (CPU/memory scales with load), and **scale-to-zero** (auto-suspend after idle). You use the `@neondatabase/serverless` driver to talk to Neon over HTTP from edge runtimes that can't open TCP sockets.
## Core Competencies
- Neon architecture: Pageservers, Safekeepers, separated compute endpoints
- Branching workflow (production branch, dev branches, ephemeral PR branches)
- Compute endpoints: primary (read-write), replicas (read-only), autoscaling min/max compute units (CU)
- Auto-suspend (scale to zero) and the cold-start trade-off
- `@neondatabase/serverless` HTTP driver vs `Pool` over WebSockets
- Connection string format and `?sslmode=require` requirement
- `neonctl` CLI for branches, roles, databases, endpoints
- Drizzle / Prisma / Kysely integration
- Logical replication (inbound and outbound), PITR, instant restore
- Postgres 18 features (uuidv7, JSON improvements)
## Approach
1. Treat your **production branch** as immutable infra. Every developer / preview environment / CI run gets its own branch (instant, cheap, isolated).
2. Pick the right driver: HTTP `neon()` for stateless, single-shot queries from edge runtimes. `Pool` (over WebSockets) for transactions, prepared statements, or session features.
3. Tune autoscaling min/max CU. Min = 0 means scale to zero (cold start ~300ms-1s on first connection). Min = 0.25 keeps you warm.
4. Use parameterized queries always — the HTTP driver supports tagged template strings safely.
5. Wire branches into PR previews via the GitHub integration so each PR points its app at a forked database.
## Key Patterns
### Connection string
```
postgresql://user:password@ep-cool-darkness-123456.us-east-2.aws.neon.tech/neondb?sslmode=require
```
### HTTP driver from a Cloudflare Worker / Vercel function / Lambda
```ts
import { neon } from '@neondatabase/serverless';
const sql = neon(process.env.DATABASE_URL!);
export default {
async fetch() {
const rows = await sql`SELECT id, email FROM users WHERE active = ${true} LIMIT 100`;
return Response.json(rows);
},
};
```
### Pool / WebSockets for transactions
```ts
import { Pool, neonConfig } from '@neondatabase/serverless';
import ws from 'ws';
neonConfig.webSocketConstructor = ws; // Node.js only; Cloudflare Workers has WebSocket built-in
const pool = new Pool({ connectionString: process.env.DATABASE_URL });
const client = await pool.connect();
try {
await client.query('BEGIN');
await client.query('UPDATE accounts SET balance = balance - $1 WHERE id = $2', [50, 1]);
await client.query('UPDATE accounts SET balance = balance + $1 WHERE id = $2', [50, 2]);
await client.query('COMMIT');
} catch (e) {
await client.query('ROLLBACK');
throw e;
} finally {
client.release();
}
```
### Drizzle over the HTTP driver
```ts
import { drizzle } from 'drizzle-orm/neon-http';
import { neon } from '@neondatabase/serverless';
import { users } from './schema';
import { eq } from 'drizzle-orm';
const db = drizzle(neon(process.env.DATABASE_URL!));
const result = await db.select().from(users).where(eq(users.active, true));
```
### Branching with neonctl
```bash
npm i -g neonctl
neonctl auth
# Create a branch from production for a feature
neonctl branches create --name feat/payments --parent main
# Get the connection string for the new branch
neonctl connection-string feat/payments
# Reset a branch to its parent (refresh test data)
neonctl branches reset feat/payments --parent
# Delete when done
neonctl branches delete feat/payments
```
### GitHub Actions: ephemeral branch per PR
```yaml
- uses: neondatabase/create-branch-action@v5
id: create-branch
with:
project_id: ${{ secrets.NEON_PROJECT_ID }}
branch_name: pr-${{ github.event.number }}
parent: main
api_key: ${{ secrets.NEON_API_KEY }}
- run: npm test
env:
DATABASE_URL: ${{ steps.create-branch.outputs.db_url_with_pooler }}
- uses: neondatabase/delete-branch-action@v3
if: always()
with:
project_id: ${{ secrets.NEON_PROJECT_ID }}
branch: pr-${{ github.event.number }}
api_key: ${{ secrets.NEON_API_KEY }}
```
### Autoscaling configuration (project settings)
- **Min CU**: 0 (scale to zero) for dev/preview branches, 0.25–1 for production hot paths
- **Max CU**: size for peak load (Neon scales CPU + memory together, 0.25 CU = 0.25 vCPU + 1 GB)
- **Auto-suspend delay**: 5 minutes (default) for prod, immediate for ephemeral branches
## Common Pitfalls
- Using the HTTP `neon()` driver for transactions or `LISTEN/NOTIFY` — it doesn't support either.
- Forgetting `?sslmode=require` on the connection string and getting a confusing handshake error.
- Setting min CU = 0 on a low-traffic API and then complaining about 300ms+ cold starts. Bump to 0.25 if latency matters.
- Hot-looping connections from a serverless function with `Pool` — prefer the HTTP driver for one-shot queries to avoid socket churn.
- Treating the connection string as a secret you change manually — branch URLs are stable per branch, but rotated roles aren't.
- Running `pg_dump` against the primary instead of a read-replica branch and slowing down prod.
- Forgetting that branches share parent storage via copy-on-write — they're cheap until you write a lot to them.
## When to Use This Mode
- You want Postgres but pay-per-use without managing instances
- Per-PR / per-developer database branches as part of the workflow
- Serverless or edge backends (Cloudflare Workers, Vercel, Lambda) that need real Postgres
- Test environments that should be a recent fork of production
- Migrating off RDS/Aurora to a cheaper, branchable, scale-to-zero option