neon-serverless-postgresql
skillConfigure serverless PostgreSQL databases on Neon with connection pooling, branching, and Edge Function integration. Apply when setting up serverless databases, connecting from Edge Functions, or managing database branches.
Claude Opus 4.5, Claude Code v2.x
apm::install
apm install @thamjiahe/neon-serverless-postgresqlapm::allowed-tools
ReadWriteEditBash
apm::skill.md
---
name: "Neon Serverless PostgreSQL"
description: "Configure serverless PostgreSQL databases on Neon with connection pooling, branching, and Edge Function integration. Apply when setting up serverless databases, connecting from Edge Functions, or managing database branches."
allowed-tools: Read, Write, Edit, Bash
version: 1.1.0
compatibility: Claude Opus 4.5, Claude Code v2.x
updated: 2026-01-24
---
# Neon Serverless PostgreSQL
Systematic Neon database setup for serverless applications with cost optimization and performance.
## Overview
This Skill enforces:
- Serverless PostgreSQL setup
- Connection pooling and HTTP connection mode
- Database branching for development
- Environment variable configuration
- Edge Function integration (Vercel, Netlify, Cloudflare)
- Zero-downtime deployments
- Autoscaling configuration
Apply when setting up serverless databases, connecting from Edge Functions, or managing environments.
## Neon Workflow
**Every Neon setup follows this process**:
```
Step 1: Create Neon project
↓
Step 2: Get connection string
↓
Step 3: Set up database branches
↓
Step 4: Configure for environment
↓
Step 5: Connect from application
↓
Step 6: Set up autoscaling
```
## Step 1: Create Neon Project
### Sign Up and Create Project
1. Visit https://neon.tech
2. Sign up with GitHub or email
3. Click "Create Project"
4. Choose region (closest to your users)
5. Select PostgreSQL version (14, 15, 16)
### Get Connection Details
Connection string format:
```
postgresql://[user]:[password]@[host].neon.tech/[dbname]?sslmode=require
```
## Step 2: Connection Modes
### Pooler Connection (Recommended for Edge Functions)
```
postgresql://[user]:[password]@[host]-pooler.neon.tech/[dbname]?sslmode=require
```
**Why pooler for Edge Functions**:
- Connection pooling (many connections share few TCP connections)
- Optimized for serverless (many short-lived connections)
- Lower latency
- Cost-effective
### Regular Connection (For long-lived connections)
```
postgresql://[user]:[password]@[host].neon.tech/[dbname]?sslmode=require
```
## Step 3: Environment Configuration
### Local Development
Create `.env.local`:
```bash
DATABASE_URL="postgresql://[user]:[password]@[host]-pooler.neon.tech/[dbname]?sslmode=require"
```
Add to `.gitignore`:
```
.env.local
.env.*.local
```
### Vercel Environment Variables
Set in Vercel dashboard → Settings → Environment Variables:
```
DATABASE_URL (for all environments: Development, Preview, Production)
```
### GitHub Secrets (for CI/CD)
```
DATABASE_URL
NEON_API_KEY
```
## Step 4: Database Branching
### Create Development Branch
```bash
# Using Neon CLI
neon branches create --name development
# Get development database connection string
neon connection-string development
```
### Git-like Branching Workflow
```
main (production database)
↓
development (feature development)
↓
feature-x (isolated testing)
```
**Benefits**:
- Data isolation between environments
- Test migrations safely
- Reset databases quickly
- PR previews with separate databases
### Manage Branches
```bash
# List all branches
neon branches list
# Create branch from main
neon branches create --name staging --parent main
# Delete branch
neon branches delete development
# Reset branch to main state
neon branches delete feature-x
neon branches create --name feature-x --parent main
```
## Step 5: Connection Strategies
### For Next.js API Routes (Server-side)
```ts
// lib/db.ts
import { Pool } from '@neondatabase/serverless';
import ws from 'ws';
// Set WebSocket constructor for Node.js < 21
if (typeof global !== 'undefined' && !global.WebSocket) {
global.WebSocket = ws as any;
}
const pool = new Pool({
connectionString: process.env.DATABASE_URL
});
export async function query(sql: string, params: unknown[] = []) {
const client = await pool.connect();
try {
return await client.query(sql, params);
} finally {
client.release();
}
}
```
### For Vercel Edge Functions
```ts
// api/edge-query.ts
import { neon } from '@neondatabase/serverless';
export const config = {
runtime: 'edge',
regions: ['iad1'] // Closest to Neon
};
export default async (req: Request) => {
const sql = neon(process.env.DATABASE_URL!);
const [user] = await sql`SELECT * FROM users WHERE id = ${123}`;
return new Response(JSON.stringify(user), {
headers: { 'content-type': 'application/json' }
});
};
```
### For Netlify Functions
```ts
// netlify/functions/query.ts
import { neon } from '@neondatabase/serverless';
export default async (event: any) => {
const sql = neon(process.env.DATABASE_URL!);
const users = await sql`SELECT * FROM users LIMIT 10`;
return {
statusCode: 200,
body: JSON.stringify(users)
};
};
```
### For Cloudflare Workers
```ts
// src/index.ts
import { neon } from '@neondatabase/serverless';
export default {
async fetch(request: Request, env: any) {
const sql = neon(env.DATABASE_URL);
const [post] = await sql`SELECT * FROM posts WHERE id = ${1}`;
return new Response(JSON.stringify(post), {
headers: { 'content-type': 'application/json' }
});
}
};
```
## Step 6: Autoscaling Configuration
### Set Compute Auto-Suspend
Neon automatically pauses compute when unused (saves costs):
```
Settings → Compute Options
- Auto-suspend: 5 minutes (default)
- Auto-suspend delay: Can be customized
```
### Set Connection Pooling Limits
```
Settings → Pooler Settings
- Pool size: 10-100 connections
- Connection timeout: 30s
```
## Step 7: Database Operations
### Create Tables
```sql
-- Using Neon SQL Editor or psql
CREATE TABLE users (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
email VARCHAR(255) NOT NULL UNIQUE,
name VARCHAR(255) NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
CREATE INDEX idx_users_email ON users(email);
```
### Query from Node.js
```ts
import { neon } from '@neondatabase/serverless';
const sql = neon(process.env.DATABASE_URL!);
// Single row query
const [user] = await sql`SELECT * FROM users WHERE id = ${userId}`;
// Multiple rows
const users = await sql`SELECT * FROM users LIMIT 10`;
// Insert
const [newUser] = await sql`
INSERT INTO users (email, name)
VALUES (${email}, ${name})
RETURNING *
`;
// Update
const [updated] = await sql`
UPDATE users
SET name = ${name}
WHERE id = ${userId}
RETURNING *
`;
// Delete
await sql`DELETE FROM users WHERE id = ${userId}`;
```
## Anti-Patterns
```ts
// ❌ BAD: Creating Pool outside request handler
const pool = new Pool({ connectionString: process.env.DATABASE_URL });
export async function GET(req: Request) {
const client = await pool.connect(); // Reuses connections
// ...
}
// ✅ GOOD: Create Pool inside request handler
export async function GET(req: Request) {
const pool = new Pool({ connectionString: process.env.DATABASE_URL });
const client = await pool.connect();
try {
// Query
} finally {
await client.release();
await pool.end();
}
}
// ❌ BAD: Connection string in code
const sql = neon('postgresql://user:password@host/db');
// ✅ GOOD: Use environment variable
const sql = neon(process.env.DATABASE_URL!);
// ❌ BAD: Forgetting to close connections
const client = await pool.connect();
const result = await client.query('SELECT * FROM users');
// No release!
// ✅ GOOD: Always release connection
const client = await pool.connect();
try {
const result = await client.query('SELECT * FROM users');
} finally {
client.release();
}
```
## Connection Troubleshooting
### Connection Timeout
```bash
# Issue: Taking too long to connect
# Solution: Use pooler connection instead of direct connection
# Change: host.neon.tech → host-pooler.neon.tech
```
### SSL Certificate Error
```bash
# Issue: SSL certificate validation failed
# Solution: Add sslmode=require to connection string
DATABASE_URL="postgresql://...?sslmode=require"
```
### Too Many Connections
```bash
# Issue: Error: too many connections
# Solution: Enable connection pooling or increase pool size
```
## Backup and Recovery
### Automatic Backups
Neon automatically backs up every transaction. Access via:
1. Neon console → Branches → branch name
2. Under "Backups" section
3. Restore from point-in-time
### Manual Export
```bash
# Export data
pg_dump postgres://user:password@host/db > backup.sql
# Restore data
psql postgres://user:password@host/db < backup.sql
```
## Verification Before Production
- [ ] Connection string configured in environment variables
- [ ] Pooler connection used for Edge Functions
- [ ] Database branches set up (main, development, staging)
- [ ] Connection pooling enabled
- [ ] Autoscaling configured
- [ ] Secrets not hardcoded
- [ ] SSL mode enabled (sslmode=require)
- [ ] Backups tested
- [ ] Read replicas configured (if needed)
- [ ] Monitoring alerts set up
## Common Operations
```bash
# Get connection string
neon connection-string
# List databases
neon databases list
# Get branch list
neon branches list
# Create backup
pg_dump $DATABASE_URL > backup.sql
# Restore from backup
psql $DATABASE_URL < backup.sql
# Reset branch (delete all data)
neon branches delete branch-name
neon branches create --name branch-name --parent main
```
## Integration with Project Standards
Enforces database best practices:
- D-1: Database models defined
- D-2: Validation at API and DB layers
- S-5: Environment variables for secrets
- No hardcoded credentials
- Connection pooling for efficiency
## Resources
- Neon Documentation: https://neon.tech/docs
- Serverless Driver: https://github.com/neondatabase/serverless
- Connection Pooling: https://neon.tech/docs/connect/connection-pooling
- Branching: https://neon.tech/docs/guide/branch
---
**Last Updated:** January 24, 2026
**Compatibility:** Claude Opus 4.5, Claude Code v2.x
**Status:** Production Ready
> **January 2026 Update:** This skill is compatible with Claude Opus 4.5 and Claude Code v2.x. For complex tasks, use the `effort: high` parameter for thorough analysis.