Neon hat die Art, wie Entwickler mit PostgreSQL arbeiten, grundlegend verändert.
Statt eines klassischen, immer laufenden Datenbankservers bietet Neon Serverless PostgreSQL:
die Datenbank skaliert auf null, wenn keine Anfragen kommen, und startet in Millisekunden wieder —
ohne eine einzige Zeile Infrastrukturcode.
Claude Code versteht Neon nativ. Von der Initialisierung des Projekts über Drizzle ORM-Schemas
bis hin zu Branch-basierten Entwicklungsworkflows — dieser Guide zeigt, wie Claude Code
und Neon zusammen moderne Fullstack-Architekturen ermöglichen.
Was du in diesem Guide lernst
- Neon Grundlagen: Compute Units, Autosuspend, Scale-to-Zero und Preismodell
- Connection Setup mit
@neondatabase/serverless für Edge-Runtimes
- Database Branching für Feature-Branches und CI/CD-Workflows
- Drizzle ORM Integration mit typsicheren Queries und Migrations
- Connection Pooling mit eingebautem PgBouncer
- Vercel + Next.js Integration mit Preview-Datenbank-Branches
1. Neon Grundlagen: Serverless vs. Classic PostgreSQL
Klassische PostgreSQL-Instanzen laufen rund um die Uhr — auch wenn niemand die Datenbank nutzt.
Das bedeutet: feste monatliche Kosten, unabhängig vom tatsaächlichen Traffic.
Neon trennt Storage und Compute konsequent voneinander und ermöglicht so Scale-to-Zero.
Compute Units (CU) und Autosuspend
Neon misst Rechenleistung in Compute Units (CU). Eine CU entspricht 1 vCPU und 4 GB RAM.
Der Free Tier bietet 0.25 CU, kostenpflichtige Pläne skalieren bis zu 10 CU.
Entscheidend ist Autosuspend: nach einer konfigurierbaren Inaktivitätszeit
(Standard: 5 Minuten) hält Neon die Compute-Instanz automatisch an.
# Neon CLI: Projekt erstellen und Branch konfigurieren
npx neon projects create \
--name my-saas-db \
--region-id aws-eu-central-1
# Autosuspend-Timeout anpassen (in Sekunden, 0 = deaktiviert)
npx neon branches update main \
--project-id prj_abc123 \
--suspend-timeout 300
Preismodell 2026
| Plan |
Compute |
Storage |
Branches |
Preis |
| Free |
0.25 CU, 191.9 CU-Std/Mo |
512 MB |
10 |
$0/Mo |
| Launch |
bis 4 CU |
10 GB inkl. |
unbegrenzt |
ab $19/Mo |
| Scale |
bis 10 CU |
50 GB inkl. |
unbegrenzt |
ab $69/Mo |
| Business |
bis 10 CU, SLA |
500 GB inkl. |
unbegrenzt |
ab $700/Mo |
Cold Start: Neon startet eine suspendierte Compute-Instanz typischerweise
in unter 500ms — für die meisten Web-Applikationen kaum wahrnehmbar.
Für latenzskritische Szenarien kann Autosuspend deaktiviert werden.
Wann lohnt sich Neon?
- Staging- und Entwicklungsumgebungen mit unregelmäßigem Traffic
- Projekte mit starken Traffic-Schwankungen (Tages-/Saisonspitzen)
- Serverless-first Architekturen auf Vercel, Cloudflare Workers, Deno Deploy
- Teams die Git-basierte DB-Workflows wollen (Branching)
- Startups im Free Tier die erst bei Wachstum zahlen wollen
2. Connection & Setup: @neondatabase/serverless
Das offizielle Neon-Paket @neondatabase/serverless ist ein Drop-in-Ersatz
für pg (node-postgres), jedoch speziell für Edge-Runtimes optimiert.
Es nutzt WebSockets und HTTP statt TCP — was in Cloudflare Workers,
Vercel Edge Functions und Deno funktioniert, wo klassisches TCP verboten ist.
Installation
npm install @neondatabase/serverless
# Optional: Drizzle ORM
npm install drizzle-orm drizzle-kit
# TypeScript-Typen
npm install -D @types/pg
Einfache Connection mit neon()
// lib/db.ts — HTTP-basiert, ideal für Edge Runtime
import { neon } from '@neondatabase/serverless';
const sql = neon(process.env.DATABASE_URL!);
// Tagged Template Literal — sicher gegen SQL-Injection
export async function getUsers() {
const users = await sql`SELECT id, name, email FROM users ORDER BY created_at DESC`;
return users;
}
// Mit Parametern — automatisch escaped
export async function getUserById(id: number) {
const [user] = await sql`SELECT * FROM users WHERE id = ${id}`;
return user ?? null;
}
Pool-basierte Connection für Node.js
// lib/pool.ts — für Node.js Runtime (kein Edge)
import { Pool } from '@neondatabase/serverless';
let pool: Pool | undefined;
export function getPool(): Pool {
if (!pool) {
pool = new Pool({
connectionString: process.env.DATABASE_URL,
max: 10, // max. Verbindungen im Pool
idleTimeoutMillis: 30_000,
connectionTimeoutMillis: 5_000,
});
}
return pool;
}
// Verwendung in einer API-Route
export async function queryWithPool<T>(
sql: string,
params: unknown[] = []
): Promise<T[]> {
const client = await getPool().connect();
try {
const { rows } = await client.query<T>(sql, params);
return rows;
} finally {
client.release();
}
}
Environment-Variablen
# .env.local
DATABASE_URL=postgresql://neondb_owner:abc123@ep-bold-fog-12345.eu-central-1.aws.neon.tech/neondb?sslmode=require
# Pooled Connection (für Connection Pooler / PgBouncer)
DATABASE_URL_UNPOOLED=postgresql://neondb_owner:abc123@ep-bold-fog-12345.eu-central-1.aws.neon.tech/neondb?sslmode=require
DATABASE_URL=postgresql://neondb_owner:abc123@ep-bold-fog-12345-pooler.eu-central-1.aws.neon.tech/neondb?sslmode=require&pgbouncer=true
Edge Runtime Kompatibilität
- Vercel Edge Functions: vollständig kompatibel via HTTP/WebSocket
- Cloudflare Workers: neon() nutzt WebSocket-Transport (fetch + WebSocket API)
- Deno Deploy: nativ unterstützt, kein TCP-Polyfill nötig
- AWS Lambda: Node.js Runtime + Pool empfohlen für warme Instanzen
- Next.js App Router: Server Components + Server Actions direkt mit neon()
3. Database Branching: Git-Workflow für Datenbanken
Das mächtigste Feature von Neon ist Database Branching. Wie Git-Branches
für Code ermöglicht Neon das Erstellen isolierter Datenbankzustände in Sekunden —
ohne Daten zu kopieren (Copy-on-Write). Jeder Branch hat seine eigene Connection String
und kann unabhängig von der Produktionsdatenbank verändert werden.
Branches erstellen und verwalten
# Neuen Feature-Branch aus main erstellen
npx neon branches create \
--project-id prj_abc123 \
--name feature/user-preferences \
--parent main
# Alle Branches auflisten
npx neon branches list --project-id prj_abc123
# Connection String eines Branch abrufen
npx neon connection-string \
--project-id prj_abc123 \
--branch feature/user-preferences
# Branch resetten auf Stand des Parent-Branches
npx neon branches reset feature/user-preferences \
--project-id prj_abc123 \
--parent
# Branch löschen nach Merge
npx neon branches delete feature/user-preferences \
--project-id prj_abc123
Programmatisches Branching via API
// neon-branch.ts — Branch via Neon API erstellen
interface NeonBranch {
id: string;
name: string;
created_at: string;
connection_uri: string;
}
async function createFeatureBranch(
projectId: string,
branchName: string
): Promise<NeonBranch> {
const response = await fetch(
`https://console.neon.tech/api/v2/projects/${projectId}/branches`,
{
method: 'POST',
headers: {
'Authorization': `Bearer ${process.env.NEON_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
branch: { name: branchName },
endpoints: [{ type: 'read_write' }],
}),
}
);
const { branch, connection_uris } = await response.json();
return { ...branch, connection_uri: connection_uris[0].connection_uri };
}
// In CI/CD: Branch für jeden PR automatisch erstellen
const prBranch = await createFeatureBranch(
process.env.NEON_PROJECT_ID!,
`pr-${process.env.GITHUB_PR_NUMBER}`
);
GitHub Actions: Branch pro Pull Request
# .github/workflows/preview-db.yml
name: Preview Database Branch
on:
pull_request:
types: [opened, synchronize, reopened]
jobs:
create-db-branch:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Create Neon Branch
uses: neondatabase/create-branch-action@v5
id: neon-branch
with:
project_id: ${{ vars.NEON_PROJECT_ID }}
branch_name: pr-${{ github.event.pull_request.number }}
api_key: ${{ secrets.NEON_API_KEY }}
- name: Run Migrations on Branch
env:
DATABASE_URL: ${{ steps.neon-branch.outputs.db_url }}
run: npx drizzle-kit migrate
Branching Best Practices
- Jeder Feature-Branch bekommt einen eigenen DB-Branch — kein Datenvänderungsrisiko
- Staging-Branch täglich von Production resetten für realistische Tests
- CI-Branches nach Merge automatisch löschen (GitHub Action)
- Branch-Namen konsistent halten:
pr-{nummer} oder feature/{name}
- Neon CLI in
package.json scripts einbinden für lokales Branching
4. Drizzle ORM Integration
Drizzle ORM ist der bevorzugte ORM für Neon-Projekte — typsicher,
schema-first und ohne magisches Runtime-Verhalten. Claude Code generiert Drizzle-Schemas
und Migrations direkt aus Anforderungen in natürlicher Sprache.
Drizzle mit Neon einrichten
// lib/drizzle.ts
import { drizzle } from 'drizzle-orm/neon-serverless';
import { Pool } from '@neondatabase/serverless';
const pool = new Pool({ connectionString: process.env.DATABASE_URL });
export const db = drizzle(pool);
// Für neon() HTTP-Client (Edge Runtime)
import { drizzle as drizzleHttp } from 'drizzle-orm/neon-http';
import { neon } from '@neondatabase/serverless';
const sql = neon(process.env.DATABASE_URL!);
export const edgeDb = drizzleHttp(sql);
Schema definieren
// db/schema.ts
import {
pgTable, serial, text, varchar, integer,
timestamp, boolean, index, unique
} from 'drizzle-orm/pg-core';
export const users = pgTable('users', {
id: serial('id').primaryKey(),
email: varchar('email', { length: 255 }).notNull().unique(),
name: text('name').notNull(),
plan: varchar('plan', { length: 20 }).default('free'),
isActive: boolean('is_active').default(true),
createdAt: timestamp('created_at').defaultNow(),
updatedAt: timestamp('updated_at').defaultNow().$onUpdate(() => new Date()),
}, (t) => ({
emailIdx: index('users_email_idx').on(t.email),
}));
export const projects = pgTable('projects', {
id: serial('id').primaryKey(),
userId: integer('user_id').notNull().references(() => users.id, { onDelete: 'cascade' }),
name: text('name').notNull(),
description: text('description'),
createdAt: timestamp('created_at').defaultNow(),
}, (t) => ({
userProjectUnique: unique().on(t.userId, t.name),
}));
// TypeScript-Typen aus Schema ableiten
export type User = typeof users.$inferSelect;
export type NewUser = typeof users.$inferInsert;
Typsichere Queries
// db/queries.ts
import { db } from './drizzle';
import { users, projects } from './schema';
import { eq, and, desc, like } from 'drizzle-orm';
// SELECT mit JOIN
export async function getUserWithProjects(userId: number) {
return db
.select({
user: users,
projectCount: projects.id,
})
.from(users)
.leftJoin(projects, eq(projects.userId, users.id))
.where(eq(users.id, userId));
}
// INSERT mit Rückgabe
export async function createUser(data: NewUser): Promise<User> {
const [newUser] = await db
.insert(users)
.values(data)
.returning();
return newUser;
}
// UPDATE mit Bedingung
export async function upgradePlan(userId: number, plan: string) {
return db
.update(users)
.set({ plan, updatedAt: new Date() })
.where(and(eq(users.id, userId), eq(users.isActive, true)))
.returning();
}
// DELETE
export async function deleteProject(projectId: number, userId: number) {
return db
.delete(projects)
.where(and(eq(projects.id, projectId), eq(projects.userId, userId)));
}
Drizzle Kit: Migrations
// drizzle.config.ts
import { defineConfig } from 'drizzle-kit';
export default defineConfig({
schema: './db/schema.ts',
out: './db/migrations',
dialect: 'postgresql',
dbCredentials: {
url: process.env.DATABASE_URL!,
},
verbose: true,
strict: true,
});
# Migration generieren + anwenden
npx drizzle-kit generate # erstellt SQL-Migration
npx drizzle-kit migrate # wendet Migration an
npx drizzle-kit studio # lokales DB-GUI
npx drizzle-kit push # direkt pushen (dev only!)
Drizzle vs. Prisma für Neon
- Drizzle: kein Runtime-Binary, kleiner Bundle, Edge-kompatibel — empfohlen für Neon
- Prisma: größerer Bundle, Prisma Accelerate nötig für Edge (extra Kosten)
- Drizzle Queries sind SQL-nah — einfacheres Debugging, kein Magic
- Prisma für Teams die ORM-Komfort über Bundle-Größe stellen
5. Connection Pooling mit PgBouncer
Serverless-Funktionen können Tausende von Datenbankverbindungen gleichzeitig aufbauen —
ein klassisches Problem das PostgreSQL schnell überlastet. Neon löst das mit einem
eingebauten PgBouncer: kein separates Setup, keine Extra-Infrastruktur.
Pooled vs. Unpooled Connection
// Neon gibt zwei Connection Strings
// 1. Direkte Verbindung (unpooled) — für Migrations, DDL
const UNPOOLED = 'postgresql://user:pass@ep-xyz.eu-central-1.aws.neon.tech/db?sslmode=require';
// 2. Pooled Verbindung — für Serverless/Edge (PgBouncer als Proxy)
const POOLED = 'postgresql://user:pass@ep-xyz-pooler.eu-central-1.aws.neon.tech/db?sslmode=require&pgbouncer=true';
// Wichtig: &pgbouncer=true deaktiviert prepared statements
// (PgBouncer Transaction Mode unterstützt keine prepared statements)
Pool-Modi: Transaction vs. Session
// Transaction Mode (Standard für Serverless)
// — Verbindung wird nach jeder Transaktion zurückgegeben
// — Ideal für stateless Serverless Functions
// — Kein SET, no advisory locks, kein LISTEN/NOTIFY
// Session Mode
// — Verbindung bleibt während gesamter Session reserviert
// — Unterstützt alle PostgreSQL-Features
// — Für langlebige Verbindungen (Node.js Server)
// Empfehlung für Neon:
const pool = new Pool({
connectionString: process.env.DATABASE_URL, // Pooled URL
max: 1, // Pro Serverless-Instanz maximal 1 Verbindung!
});
// In Serverless: Pool NICHT global initialisieren
// Stattdessen: für jeden Request neue Verbindung via neon()
Best Practices für Serverless Connection Management
// api/users/route.ts — Next.js App Router
import { neon } from '@neondatabase/serverless';
import { NextResponse } from 'next/server';
// neon() ist leichtgewichtig — ok für jeden Request neu zu erstellen
export async function GET() {
const sql = neon(process.env.DATABASE_URL!);
try {
const users = await sql`
SELECT id, name, email, plan, created_at
FROM users
WHERE is_active = true
ORDER BY created_at DESC
LIMIT 50
`;
return NextResponse.json({ users });
} catch (err) {
console.error('DB Error:', err);
return NextResponse.json(
{ error: 'Datenbankfehler' },
{ status: 500 }
);
}
}
Verbindungslimits beachten
- Free Tier: max. 20 gleichzeitige Verbindungen (unpooled)
- Mit Pooler: bis zu 10.000 Client-Verbindungen möglich
- Prepared Statements im Transaction Mode deaktivieren:
prepare: false
- Drizzle: automatisch korrekt konfiguriert bei Pooled URL
- Bei "too many connections": Pooler-URL statt direkter URL verwenden
6. Vercel + Next.js Integration
Neon ist die offizielle PostgreSQL-Datenbank für Vercel. Mit der nativen Integration
werden Datenbank-Branches automatisch mit Vercel Preview Deployments verknüpft —
jeder Pull Request bekommt seine eigene isolierte Datenbankumgebung.
@vercel/postgres auf Neon-Basis
// Vercel empfiehlt direkt @neondatabase/serverless (2024+)
// @vercel/postgres ist ein Wrapper um Neon
npm install @neondatabase/serverless
// In Vercel Dashboard: Storage → Neon → Add Store
// Automatisch: POSTGRES_URL, POSTGRES_URL_NON_POOLING werden gesetzt
// app/lib/db.ts
import { neon } from '@neondatabase/serverless';
// Vercel setzt POSTGRES_URL automatisch
export const sql = neon(process.env.POSTGRES_URL!);
Server Actions mit Neon und Drizzle
// app/actions/users.ts
'use server'
import { db } from '@/lib/drizzle';
import { users } from '@/db/schema';
import { eq } from 'drizzle-orm';
import { revalidatePath } from 'next/cache';
import { z } from 'zod';
const CreateUserSchema = z.object({
name: z.string().min(2).max(100),
email: z.string().email(),
});
export async function createUserAction(formData: FormData) {
const parsed = CreateUserSchema.safeParse({
name: formData.get('name'),
email: formData.get('email'),
});
if (!parsed.success) {
return { error: parsed.error.flatten() };
}
const [newUser] = await db
.insert(users)
.values(parsed.data)
.returning();
revalidatePath('/dashboard/users');
return { success: true, user: newUser };
}
Preview Deployments mit eigenen DB-Branches
# vercel.json — Neon Branch Automation
{
"env": {
"NEON_PROJECT_ID": "prj_abc123"
}
}
# GitHub Actions: DB Branch für PR + Vercel Preview verknüpfen
# .github/workflows/preview.yml
name: Preview Deploy with DB Branch
on:
pull_request:
env:
NEON_PROJECT_ID: ${{ vars.NEON_PROJECT_ID }}
jobs:
deploy-preview:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Create Neon DB Branch
id: neon
uses: neondatabase/create-branch-action@v5
with:
project_id: ${{ env.NEON_PROJECT_ID }}
branch_name: preview/pr-${{ github.event.number }}
api_key: ${{ secrets.NEON_API_KEY }}
- name: Run Migrations
env:
DATABASE_URL: ${{ steps.neon.outputs.db_url }}
run: npx drizzle-kit migrate
- name: Deploy to Vercel
uses: amondnet/vercel-action@v25
with:
vercel-token: ${{ secrets.VERCEL_TOKEN }}
vercel-org-id: ${{ secrets.VERCEL_ORG_ID }}
vercel-project-id: ${{ secrets.VERCEL_PROJECT_ID }}
scope: ${{ secrets.VERCEL_ORG_ID }}
env:
DATABASE_URL: ${{ steps.neon.outputs.db_url }}
Produktions-Checkliste
// Typischer Neon + Next.js + Drizzle Stack 2026
// package.json scripts
{
"scripts": {
"db:generate": "drizzle-kit generate",
"db:migrate": "drizzle-kit migrate",
"db:migrate:prod": "DATABASE_URL=$DATABASE_URL_UNPOOLED drizzle-kit migrate",
"db:studio": "drizzle-kit studio",
"db:push": "drizzle-kit push"
}
}
// WICHTIG: Migrations IMMER mit unpooled URL ausführen!
// DDL (CREATE TABLE, ALTER TABLE) funktioniert nicht über PgBouncer
Vollständiger Stack 2026
- Datenbank: Neon Serverless PostgreSQL (Launch Plan, eu-central-1)
- ORM: Drizzle ORM + drizzle-kit für Migrations
- Framework: Next.js 15 App Router + Server Actions
- Hosting: Vercel (Production + Preview Deployments)
- Connection: neon() für Edge, Pool für Node.js API Routes
- Validierung: Zod für Eingaben, Drizzle Typen für DB-Output
- Auth: Clerk oder NextAuth.js mit Neon als Session-Store
Fazit: Neon und Claude Code 2026
Neon hat sich als de-facto Standard für Serverless PostgreSQL etabliert. Die Kombination
aus Scale-to-Zero, Database Branching und nativer
Edge-Kompatibilität macht Neon zur idealen Datenbank für moderne Fullstack-Applikationen.
Claude Code versteht die Neon-Architektur nativ: von der initialen Projektstruktur
über Drizzle-Schema-Design bis zu Branch-basierten CI/CD-Workflows. Statt Dokumentation
zu lesen und Boilerplate manuell zu schreiben, beschreibst du deine Anforderungen —
und Claude Code generiert produktionsbereiten, typsicheren Code.
Tipp: Neon Free Tier ist dauerhaft kostenlos — ideal für Projekte
in der Frühphase. Bei Überschreitung der 191.9 CU-Stunden wird Compute automatisch
gestoppt (nicht gekündigt). Scale-up mit einem Klick im Dashboard.
Claude Code für dein Neon-Projekt
Serverless PostgreSQL mit Drizzle ORM, typsichere Queries, Branch-basierte Workflows —
Claude Code generiert deinen kompletten Neon-Stack in Minuten.
Jetzt kostenlos testen und das erste Schema generieren lassen.
14 Tage kostenlos testen →