Install any skill in seconds. Free to start, no credit card required.
Get Started Free →Neon PostgreSQL serverless database - connection pooling, branching, serverless driver, and optimization. Use when deploying to Neon or building serverless applications.
.claude/skills/aiskillstore-neon-postgres/SKILL.md| Test case | Without → With | Effect | Δ tokens | Δ turns |
|---|---|---|---|---|
| case-08 | ✗→✓ | ▲ Improved | 314% | 0% |
| case-09 | ✗→✓ | ▲ Improved | 131% | 0% |
| case-12 | ✗→✓ | ▲ Improved | 10% | 0% |
| case-24 | ✓→✓ | = Same ✓ | 72% | 0% |
| case-22 | ✓→✓ | = Same ✓ | 60% | 0% |
Serverless PostgreSQL with branching, autoscaling, and instant provisioning.
bash# npm npm install @neondatabase/serverless # pnpm pnpm add @neondatabase/serverless # yarn yarn add @neondatabase/serverless # bun bun add @neondatabase/serverless
env# Direct connection (for migrations, scripts) DATABASE_URL=postgresql://user:password@ep-xxx.us-east-1.aws.neon.tech/dbname?sslmode=require # Pooled connection (for application) DATABASE_URL_POOLED=postgresql://user:password@ep-xxx-pooler.us-east-1.aws.neon.tech/dbname?sslmode=require
| Concept | Guide | |---------|-------| | Serverless Driver | reference/serverless-driver.md | | Connection Pooling | reference/pooling.md | | Branching | reference/branching.md | | Autoscaling | reference/autoscaling.md |
| Pattern | Guide | |---------|-------| | Next.js Integration | examples/nextjs.md | | Edge Functions | examples/edge.md | | Migrations | examples/migrations.md | | Branching Workflow | examples/branching-workflow.md |
| Template | Purpose | |----------|---------| | templates/db.ts | Database connection | | templates/neon.config.ts | Neon configuration |
Best for: Edge functions, serverless, one-shot queries
typescriptimport { neon } from "@neondatabase/serverless"; const sql = neon(process.env.DATABASE_URL!); // Simple query const posts = await sql`SELECT * FROM posts WHERE published = true`; // With parameters const post = await sql`SELECT * FROM posts WHERE id = ${postId}`; // Insert await sql`INSERT INTO posts (title, content) VALUES (${title}, ${content})`;
Best for: Long-running connections, transactions
typescriptimport { Pool } from "@neondatabase/serverless"; const pool = new Pool({ connectionString: process.env.DATABASE_URL }); const client = await pool.connect(); try { await client.query("BEGIN"); await client.query("INSERT INTO posts (title) VALUES ($1)", [title]); await client.query("COMMIT"); } catch (e) { await client.query("ROLLBACK"); throw e; } finally { client.release(); }
typescript// src/db/index.ts import { neon } from "@neondatabase/serverless"; import { drizzle } from "drizzle-orm/neon-http"; import * as schema from "./schema"; const sql = neon(process.env.DATABASE_URL!); export const db = drizzle(sql, { schema });
typescript// src/db/index.ts import { Pool } from "@neondatabase/serverless"; import { drizzle } from "drizzle-orm/neon-serverless"; import * as schema from "./schema"; const pool = new Pool({ connectionString: process.env.DATABASE_URL }); export const db = drizzle(pool, { schema });
Neon branches are copy-on-write clones of your database.
bash# Install Neon CLI npm install -g neonctl # Login neonctl auth # List branches neonctl branches list # Create branch neonctl branches create --name feature-x # Get connection string neonctl connection-string feature-x # Delete branch neonctl branches delete feature-x
bash# Create branch for feature neonctl branches create --name feature-auth --parent main # Get connection string for branch export DATABASE_URL=$(neonctl connection-string feature-auth) # Work on feature... # When done, merge via application migrations neonctl branches delete feature-auth
yaml# .github/workflows/preview.yml name: Preview on: pull_request jobs: preview: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: Create Neon Branch uses: neondatabase/create-branch-action@v5 id: branch with: project_id: ${{ secrets.NEON_PROJECT_ID }} api_key: ${{ secrets.NEON_API_KEY }} branch_name: preview-${{ github.event.pull_request.number }} - name: Run Migrations env: DATABASE_URL: ${{ steps.branch.outputs.db_url }} run: npx drizzle-kit migrate
| Scenario | Connection Type | |----------|-----------------| | Edge/Serverless functions | HTTP (neon) | | API routes with transactions | WebSocket Pool | | Long-running processes | WebSocket Pool | | One-shot queries | HTTP (neon) |
env# Without pooler (direct) postgresql://user:pass@ep-xxx.aws.neon.tech/db # With pooler (add -pooler to endpoint) postgresql://user:pass@ep-xxx-pooler.aws.neon.tech/db
Configure in Neon console:
typescriptimport { neon } from "@neondatabase/serverless"; const sql = neon(process.env.DATABASE_URL!, { fetchOptions: { // Increase timeout for cold starts signal: AbortSignal.timeout(10000), }, });
typescript// Good - HTTP for serverless import { neon } from "@neondatabase/serverless"; const sql = neon(process.env.DATABASE_URL!); // Avoid - Pool in serverless (connection exhaustion) import { Pool } from "@neondatabase/serverless"; const pool = new Pool({ connectionString: process.env.DATABASE_URL });
env# .env.development DATABASE_URL=postgresql://...@ep-dev-branch... # .env.production DATABASE_URL=postgresql://...@ep-main...
typescript// Good - parameterized query const result = await sql`SELECT * FROM users WHERE id = ${userId}`; // Bad - string interpolation (SQL injection risk) const result = await sql(`SELECT * FROM users WHERE id = '${userId}'`);
typescriptimport { neon, NeonDbError } from "@neondatabase/serverless"; const sql = neon(process.env.DATABASE_URL!); try { await sql`INSERT INTO users (email) VALUES (${email})`; } catch (error) { if (error instanceof NeonDbError) { if (error.code === "23505") { // Unique violation throw new Error("Email already exists"); } } throw error; }
typescript// app/posts/page.tsx import { neon } from "@neondatabase/serverless"; const sql = neon(process.env.DATABASE_URL!); export default async function PostsPage() { const posts = await sql`SELECT * FROM posts ORDER BY created_at DESC`; return ( <ul> {posts.map((post) => ( <li key={post.id}>{post.title}</li> ))} </ul> ); }
typescript// src/db/index.ts import { neon } from "@neondatabase/serverless"; import { drizzle } from "drizzle-orm/neon-http"; import * as schema from "./schema"; const sql = neon(process.env.DATABASE_URL!); export const db = drizzle(sql, { schema }); // src/db/schema.ts import { pgTable, serial, text, timestamp } from "drizzle-orm/pg-core"; export const posts = pgTable("posts", { id: serial("id").primaryKey(), title: text("title").notNull(), content: text("content"), createdAt: timestamp("created_at").defaultNow().notNull(), }); // drizzle.config.ts import { defineConfig } from "drizzle-kit"; export default defineConfig({ schema: "./src/db/schema.ts", out: "./src/db/migrations", dialect: "postgresql", dbCredentials: { url: process.env.DATABASE_URL!, }, });
| Case | Status | Duration (ms) | Turns | Tokens | Tool calls | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Without | With | Δ | Without | With | Δ | Without | With | Δ | Without | With | Δ | ||
case-24 | pass→pass | 18,913 | 25,547 | +35% | 1 | 1 | 0% | 2,886 | 4,973 | +72% | 0 | 0 | — |
case-08 | fail→pass | 7,766 | 9,802 | +26% | 1 | 1 | 0% | 632 | 2,616 | +314% | 0 | 0 | — |
case-09 | fail→pass | 20,347 | 10,845 | -47% | 1 | 1 | 0% | 1,193 | 2,761 | +131% | 0 | 0 | — |
case-22 | pass→pass | 21,808 | 20,209 | -7% | 1 | 1 | 0% | 3,129 | 5,021 | +60% | 0 | 0 | — |
case-01 | pass→pass | 37,690 | 50,095 | +33% | 1 | 1 | 0% | 1,271 | 2,820 | +122% | 0 | 0 | — |
case-02 | pass→pass | 32,277 | 31,341 | -3% | 1 | 1 | 0% | 2,493 | 3,540 | +42% | 0 | 0 | — |
case-03 | pass→pass | 19,505 | 25,430 | +30% | 1 | 1 | 0% | 2,539 | 3,602 | +42% | 0 | 0 | — |
case-04 | pass→pass | 15,978 | 24,928 | +56% | 1 | 1 | 0% | 1,771 | 3,057 | +73% | 0 | 0 | — |
case-05 | pass→pass | 15,043 | 13,947 | -7% | 1 | 1 | 0% | 1,657 | 3,380 | +104% | 0 | 0 | — |
case-06 | pass→pass | 6,291 | 4,029 | -36% | 1 | 1 | 0% | 959 | 2,853 | +197% | 0 | 0 | — |
case-07 | pass→pass | 10,012 | 9,226 | -8% | 1 | 1 | 0% | 791 | 2,935 | +271% | 0 | 0 | — |
case-10 | pass→pass | 15,963 | 10,745 | -33% | 1 | 1 | 0% | 1,590 | 2,759 | +74% | 0 | 0 | — |
case-11 | pass→pass | 10,040 | 9,953 | -1% | 1 | 1 | 0% | 885 | 2,950 | +233% | 0 | 0 | — |
case-12 | fail→pass | 60,442 | 13,452 | -78% | 1 | 1 | 0% | 3,407 | 3,734 | +10% | 0 | 0 | — |
case-13 | pass→pass | 14,958 | 12,832 | -14% | 1 | 1 | 0% | 1,783 | 4,040 | +127% | 0 | 0 | — |
case-14 | pass→pass | 25,304 | 6,358 | -75% | 1 | 1 | 0% | 1,938 | 2,856 | +47% | 0 | 0 | — |
case-15 | pass→pass | 12,445 | 14,491 | +16% | 1 | 1 | 0% | 2,469 | 4,281 | +73% | 0 | 0 | — |
case-16 | pass→pass | 6,405 | 7,785 | +22% | 1 | 1 | 0% | 507 | 2,668 | +426% | 0 | 0 | — |
case-17 | pass→pass | 11,524 | 3,018 | -74% | 1 | 1 | 0% | 1,202 | 2,642 | +120% | 0 | 0 | — |
case-23 | pass→pass | 18,898 | 21,315 | +13% | 1 | 1 | 0% | 2,945 | 5,113 | +74% | 0 | 0 | — |
case-18 | pass→pass | 2,969 | 6,955 | +134% | 1 | 1 | 0% | 421 | 2,520 | +499% | 0 | 0 | — |
case-19 | pass→pass | 14,080 | 7,124 | -49% | 1 | 1 | 0% | 1,380 | 2,593 | +88% | 0 | 0 | — |
case-20 | pass→pass | 12,346 | 10,776 | -13% | 1 | 1 | 0% | 541 | 2,523 | +366% | 0 | 0 | — |
case-21 | pass→pass | 9,900 | 7,296 | -26% | 1 | 1 | 0% | 491 | 2,547 | +419% | 0 | 0 | — |
DecimalAI ran this skill against gemini-3.6-flash twice over the same eval suite — once with the skill loaded and once without — and compared the two runs case by case. 24 cases were attempted. The headline lift of +13 percentage points is the difference between those two pass rates over the 24 comparable cases.
Without the skill loaded, the model failed this case. With it loaded, the same prompt on the same model passed. This is one improved case from the latest verified run; every case, including any that regressed, is in the table above.
Other measured skills in the registry, with their headline benchmark lift.