
Using Neon
- 108 installs
- 30.1k repo stars
- Updated August 4, 2026
- davila7/claude-code-templates
Provision Neon serverless Postgres, environment branches, connection strings, and schema workflows while wiring app backends during development.
About
Guides Claude Code through Neon serverless PostgreSQL setup including project creation, branch databases per environment, secure connection strings, and integration patterns for modern SaaS and API backends requiring scalable relational storage.
- Serverless Postgres setup
- Database branching per env
- Connection string management
- Schema migration guidance
- Neon project provisioning
Using Neon by the numbers
- 108 all-time installs (skills.sh)
- Ranked #320 of 911 Databases skills by installs in the Skillselion catalog
- Data as of Aug 5, 2026 (Skillselion catalog sync)
npx skills add https://github.com/davila7/claude-code-templates --skill using-neonAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 108 |
|---|---|
| repo stars | ★ 30.1k |
| Last updated | August 4, 2026 |
| Repository | davila7/claude-code-templates ↗ |
What it does
Provision Neon serverless Postgres, environment branches, connection strings, and schema workflows while wiring app backends during development.
Files
Neon Serverless Postgres
Neon is a serverless Postgres platform that separates compute and storage to offer autoscaling, branching, instant restore, and scale-to-zero. It's fully compatible with Postgres and works with any language, framework, or ORM that supports Postgres.
Neon Documentation
Always reference the Neon documentation before making Neon-related claims. The documentation is the source of truth for all Neon-related information.
Below you'll find a list of resources organized by area of concern. This is meant to support you find the right documentation pages to fetch and add a bit of additonal context.
You can use the curl commands to fetch the documentation page as markdown:
Documentation:
# Get list of all Neon docs
curl https://neon.tech/llms.txt
# Fetch any doc page as markdown
curl -H "Accept: text/markdown" https://neon.tech/docs/<path>Don't guess docs pages. Use the llms.txt index to find the relevant URL or follow the links in the resources below.
Overview of Resources
Reference the appropriate resource file based on the user's needs:
Core Guides
| Area | Resource | When to Use |
|---|---|---|
| What is Neon | references/what-is-neon.md | Understanding Neon concepts, architecture, core resources |
| Referencing Docs | references/referencing-docs.md | Looking up official documentation, verifying information |
| Features | references/features.md | Branching, autoscaling, scale-to-zero, instant restore |
| Getting Started | references/getting-started.md | Setting up a project, connection strings, dependencies, schema |
| Connection Methods | references/connection-methods.md | Choosing drivers based on platform and runtime |
| Developer Tools | references/devtools.md | VSCode extension, MCP server, Neon CLI (neon init) |
Database Drivers & ORMs
HTTP/WebSocket queries for serverless/edge functions.
| Area | Resource | When to Use |
|---|---|---|
| Serverless Driver | references/neon-serverless.md | @neondatabase/serverless - HTTP/WebSocket queries |
| Drizzle ORM | references/neon-drizzle.md | Drizzle ORM integration with Neon |
Auth & Data API SDKs
Authentication and PostgREST-style data API for Neon.
| Area | Resource | When to Use |
|---|---|---|
| Neon Auth | references/neon-auth.md | @neondatabase/auth - Authentication only |
| Neon JS SDK | references/neon-js.md | @neondatabase/neon-js - Auth + Data API (PostgREST-style queries) |
Neon Platform API & CLI
Managing Neon resources programmatically via REST API, SDKs, or CLI.
| Area | Resource | When to Use |
|---|---|---|
| Platform API Overview | references/neon-platform-api.md | Managing Neon resources via REST API |
| Neon CLI | references/neon-cli.md | Terminal workflows, scripts, CI/CD pipelines |
| TypeScript SDK | references/neon-typescript-sdk.md | @neondatabase/api-client |
| Python SDK | references/neon-python-sdk.md | neon-api package |
Connection Methods
Guide to selecting the optimal connection method for your Neon Postgres database based on deployment platform and runtime environment.
For official documentation:
curl -H "Accept: text/markdown" https://neon.tech/docs/connect/choose-connectionDecision Tree
Follow this flow to determine the right connection approach:
1. What Language Are You Using?
Not TypeScript/JavaScript → Use TCP with connection pooling from a secure server.
For non-TypeScript languages, connect from a secure backend server using your language's native Postgres driver with connection pooling enabled.
| Language/Framework | Documentation |
|---|---|
| Django (Python) | https://neon.tech/docs/guides/django |
| SQLAlchemy (Python) | https://neon.tech/docs/guides/sqlalchemy |
| Elixir Ecto | https://neon.tech/docs/guides/elixir-ecto |
| Laravel (PHP) | https://neon.tech/docs/guides/laravel |
| Ruby on Rails | https://neon.tech/docs/guides/ruby-on-rails |
| Go | https://neon.tech/docs/guides/go |
| Rust | https://neon.tech/docs/guides/rust |
| Java | https://neon.tech/docs/guides/java |
TypeScript/JavaScript → Continue to step 2.
---
2. Client-Side App Without Backend?
Yes → Use Neon Data API via @neondatabase/neon-js
This is the only option for client-side apps since browsers cannot make direct TCP connections to Postgres. See neon-js.md for setup.
curl -H "Accept: text/markdown" https://neon.tech/docs/reference/javascript-sdkNo → Continue to step 3.
---
3. Long-Running Server? (Railway, Render, traditional VPS)
Yes → Use TCP with connection pooling via node-postgres, postgres.js, or bun:pg
Long-running servers maintain persistent connections, so standard TCP drivers with pooling are optimal.
No → Continue to step 4.
---
4. Edge Environment Without TCP Support?
Some edge runtimes don't support TCP connections. Rarely the case anymore.
Yes → Continue to step 5 to check transaction requirements.
No → Continue to step 6 to check pooling support.
---
5. Does Your App Use SQL Transactions?
Yes → Use WebSocket transport via @neondatabase/serverless with Pool
WebSocket maintains connection state needed for transactions. See neon-serverless.md for setup.
No → Use HTTP transport via @neondatabase/serverless
HTTP is faster for single queries (~3 roundtrips vs ~8 for TCP). See neon-serverless.md for setup.
curl -H "Accept: text/markdown" https://neon.tech/docs/serverless/serverless-driver---
6. Serverless Environment With Connection Pooling Support?
Vercel (Fluid Compute) → Use TCP with `@vercel/functions`
Vercel's Fluid compute supports connection pooling. Use attachDatabasePool for optimal connection management.
curl -H "Accept: text/markdown" https://neon.tech/docs/guides/vercel-connection-methodsCloudflare (with Hyperdrive) → Use TCP via Hyperdrive
Cloudflare Hyperdrive provides connection pooling for Workers. Use node-postgres or any native TCP driver.
See https://neon.tech/docs/guides/cloudflare-hyperdrive for more on connecting with Cloudflare Workers and Hyperdrive.
No pooling support (Netlify, Deno Deploy) → Use @neondatabase/serverless
Fall back to the decision in step 5 based on transaction requirements.
---
Quick Reference Table
| Platform | TCP Support | Pooling | Recommended Driver |
|---|---|---|---|
| Vercel (Fluid) | Yes | @vercel/functions | pg (node-postgres) |
| Cloudflare (Hyperdrive) | Yes | Hyperdrive | pg (node-postgres) |
| Cloudflare Workers | No | No | @neondatabase/serverless |
| Netlify Functions | No | No | @neondatabase/serverless |
| Deno Deploy | No | No | @neondatabase/serverless |
| Railway / Render | Yes | Built-in | pg (node-postgres) |
| Client-side (browser) | No | N/A | @neondatabase/neon-js |
---
ORM Support
Popular TypeScript/JavaScript ORMs all work with Neon:
| ORM | Drivers Supported | Documentation |
|---|---|---|
| Drizzle | pg, postgres.js, @neondatabase/serverless | https://neon.tech/docs/guides/drizzle |
| Kysely | pg, postgres.js, @neondatabase/serverless | https://neon.tech/docs/guides/kysely |
| Prisma | pg, @neondatabase/serverless | https://neon.tech/docs/guides/prisma |
| TypeORM | pg | https://neon.tech/docs/guides/typeorm |
All ORMs support both TCP drivers and Neon's serverless driver depending on your platform.
For Drizzle ORM integration with Neon, see neon-drizzle.md.
---
Vercel Fluid + Drizzle Example
Complete database client setup for Vercel with Drizzle ORM and connection pooling. See neon-drizzle.md for more examples.
// src/lib/db/client.ts
import { attachDatabasePool } from "@vercel/functions";
import { drizzle } from "drizzle-orm/node-postgres";
import { Pool } from "pg";
import * as schema from "./schema";
const pool = new Pool({
connectionString: process.env.DATABASE_URL,
});
attachDatabasePool(pool);
export const db = drizzle({ client: pool, schema });Why `attachDatabasePool`?
- First request establishes the TCP connection (~8 roundtrips)
- Subsequent requests reuse the connection instantly
- Ensures idle connections close gracefully before function suspension
- Prevents connection leaks in serverless environments
---
Gathering Requirements
When helping a user choose their connection method, gather this information:
1. Deployment platform: Where will the app run? (Vercel, Cloudflare, Netlify, Railway, browser, etc.) 2. Runtime type: Serverless functions, edge functions, or long-running server? 3. Transaction requirements: Does the app need SQL transactions? 4. ORM preference: Using Drizzle, Kysely, Prisma, or raw SQL?
Then provide:
- The recommended driver/package
- A working code example for their setup
- The correct npm install command
---
Documentation Resources
| Topic | URL |
|---|---|
| Choosing Connection Method | https://neon.tech/docs/connect/choose-connection |
| Serverless Driver | https://neon.tech/docs/serverless/serverless-driver |
| JavaScript SDK | https://neon.tech/docs/reference/javascript-sdk |
| Connection Pooling | https://neon.tech/docs/connect/connection-pooling |
| Vercel Connection Methods | https://neon.tech/docs/guides/vercel-connection-methods |
Neon Developer Tools
Neon provides developer tools to enhance your local development workflow, including a VSCode extension and MCP server for AI-assisted development.
Quick Setup with neon init
The fastest way to set up all Neon developer tools:
npx neon initThis command:
- Installs the Neon VSCode extension
- Configures the Neon MCP server for AI assistants
- Sets up your local environment for Neon development
For full CLI reference:
curl -H "Accept: text/markdown" https://neon.tech/docs/reference/cli-initVSCode Extension
The Neon VSCode extension provides:
- Database Explorer: Browse projects, branches, tables, and data
- SQL Editor: Write and execute queries with IntelliSense
- Branch Management: Create, switch, and manage database branches
- Connection String Access: Quick copy of connection strings
Install from VSCode:
1. Open Extensions (Cmd/Ctrl+Shift+X) 2. Search "Neon" 3. Install "Neon" by Neon
Or via command line:
code --install-extension neon.neon-vscodeFor detailed documentation:
curl -H "Accept: text/markdown" https://neon.tech/docs/local/vscode-extensionNeon MCP Server
The Neon MCP (Model Context Protocol) server enables AI assistants like Claude, Cursor, and GitHub Copilot to interact with your Neon databases directly.
Capabilities
The MCP server provides AI assistants with:
- Project Management: List, create, describe, and delete projects
- Branch Operations: Create branches, compare schemas, reset from parent
- SQL Execution: Run queries and transactions
- Schema Operations: Describe tables, get database structure
- Migrations: Prepare and complete database migrations with safety checks
- Query Tuning: Analyze and optimize slow queries
- Neon Auth: Provision authentication for your branches
Setup
Option 1: Via neon init (Recommended)
npx neon initOption 2: Manual Configuration
Add to your AI assistant's MCP configuration:
{
"mcpServers": {
"neon": {
"command": "npx",
"args": ["-y", "@neondatabase/mcp-server-neon"],
"env": {
"NEON_API_KEY": "your-api-key"
}
}
}
}Get your API key from: https://console.neon.tech/app/settings/api-keys
Common MCP Operations
| Operation | What It Does |
|---|---|
list_projects | Show all Neon projects |
create_project | Create a new project |
run_sql | Execute SQL queries |
get_connection_string | Get database connection URL |
create_branch | Create a database branch |
prepare_database_migration | Safely prepare schema changes |
provision_neon_auth | Set up Neon Auth |
For full MCP server documentation:
curl -H "Accept: text/markdown" https://neon.tech/docs/ai/neon-mcp-serverDocumentation Resources
| Topic | URL |
|---|---|
| CLI Init Command | https://neon.tech/docs/reference/cli-init |
| VSCode Extension | https://neon.tech/docs/local/vscode-extension |
| MCP Server | https://neon.tech/docs/ai/neon-mcp-server |
| Neon CLI Reference | https://neon.tech/docs/reference/neon-cli |
Neon Features
Overview of Neon's key platform features. For detailed information, fetch the official docs.
Branching
Create instant, copy-on-write clones of your database at any point in time. Branches are isolated environments perfect for development, testing, and preview deployments.
curl -H "Accept: text/markdown" https://neon.tech/docs/introduction/branchingKey Points:
- Branches are instant (no data copying)
- Copy-on-write means branches only store changes from parent
- Use for: dev environments, staging, testing, preview deployments
- Branches can have their own compute endpoint
Use Cases:
| Use Case | Description |
|---|---|
| Development | Each developer gets isolated branch |
| Preview Deployments | Branch per PR/preview URL |
| Testing | Reset test data by recreating branch |
| Schema Migrations | Test migrations on branch before production |
If the Neon MCP server is available, you can use it to list and create branches. Otherwise, refer to the Neon CLI or Platform API.
Autoscaling
Neon automatically scales compute resources based on workload demand.
curl -H "Accept: text/markdown" https://neon.tech/docs/introduction/autoscalingKey Points:
- Scales between min and max compute units (CUs)
- Responds to CPU and memory pressure
- No manual intervention required
- Configure limits per project or endpoint
Scale to Zero
Databases automatically suspend after a period of inactivity, reducing costs to storage-only.
curl -H "Accept: text/markdown" https://neon.tech/docs/introduction/scale-to-zeroKey Points:
- Default suspend after 5 minutes of inactivity (configurable)
- First query after suspend has ~500ms cold start
- Storage is always maintained
- Perfect for dev/staging environments with intermittent use
Instant Restore
Restore your database to any point within your retention window without backups.
curl -H "Accept: text/markdown" https://neon.tech/docs/introduction/branch-restoreKey Points:
- Point-in-time recovery without pre-configured backups
- Restore window depends on plan (7-30 days)
- Create branches from any point in history
- Time Travel queries to view historical data
Read Replicas
Create read-only compute endpoints to scale read workloads.
curl -H "Accept: text/markdown" https://neon.tech/docs/introduction/read-replicasKey Points:
- Read replicas share storage with primary (no data duplication)
- Instant creation
- Independent scaling from primary
- Use for: analytics, reporting, read-heavy workloads
Connection Pooling
Built-in connection pooling via PgBouncer for efficient connection management.
curl -H "Accept: text/markdown" https://neon.tech/docs/connect/connection-poolingKey Points:
- Enabled by adding
-poolerto endpoint hostname - Transaction mode by default
- Supports up to 10,000 concurrent connections
- Essential for serverless environments
IP Allow Lists
Restrict database access to specific IP addresses or ranges.
curl -H "Accept: text/markdown" https://neon.tech/docs/introduction/ip-allowLogical Replication
Replicate data to/from external Postgres databases.
curl -H "Accept: text/markdown" https://neon.tech/docs/guides/logical-replication-guideNeon Auth
Managed authentication that branches with your database.
curl -H "Accept: text/markdown" https://neon.tech/docs/auth/overviewKey Points:
- Sign-in/sign-up with email, social providers (Google, GitHub)
- Session management
- UI components included
- Branches with your database
For setup, see neon-auth.md. For auth + data API, see neon-js.md.
Feature Documentation Reference
| Feature | Documentation | Resource |
|---|---|---|
| Branching | https://neon.tech/docs/introduction/branching | - |
| Autoscaling | https://neon.tech/docs/introduction/autoscaling | - |
| Scale to Zero | https://neon.tech/docs/introduction/scale-to-zero | - |
| Instant Restore | https://neon.tech/docs/introduction/branch-restore | - |
| Read Replicas | https://neon.tech/docs/introduction/read-replicas | - |
| Connection Pooling | https://neon.tech/docs/connect/connection-pooling | - |
| IP Allow | https://neon.tech/docs/introduction/ip-allow | - |
| Logical Replication | https://neon.tech/docs/guides/logical-replication-guide | - |
| Neon Auth | https://neon.tech/docs/auth/overview | neon-auth.md |
| Data API | https://neon.tech/docs/data-api/overview | neon-js.md |
Getting Started with Neon
Interactive guide to help users get started with Neon in their project. Sets up their Neon project (with a connection string) and connects their database to their code.
For the official getting started guide:
curl -H "Accept: text/markdown" https://neon.tech/docs/get-started/signing-upInteractive Setup Flow
Step 1: Check Organizations and Projects
First, check for organizations:
- If they have 1 organization: Default to that organization
- If they have multiple organizations: List all and ask which one to use
Then, check for projects within the selected organization:
- No projects: Ask if they want to create a new project
- 1 project: Ask "Would you like to use '{project_name}' or create a new one?"
- Multiple projects (<6): List all and let them choose
- Many projects (6+): List recent projects, offer to create new or specify by name/ID
Step 2: Database Setup
Get the connection string:
- Use the MCP server to get the connection string for the selected project
Configure it for their environment:
- Most projects use a
.envfile withDATABASE_URL - For other setups, check project structure and ask
Before modifying .env:
1. Try to read the .env file first 2. If readable: Use search_replace to update or append 3. If unreadable: Use append command or show the line to add manually:
DATABASE_URL=postgresql://user:password@host/databaseStep 3: Install Dependencies
Recommend drivers based on deployment platform and runtime. For detailed guidance, see connection-methods.md.
Quick Recommendations:
| Environment | Driver | Install |
|---|---|---|
| Vercel (Edge/Serverless) | @neondatabase/serverless | npm install @neondatabase/serverless |
| Cloudflare Workers | @neondatabase/serverless | npm install @neondatabase/serverless |
| AWS Lambda | @neondatabase/serverless | npm install @neondatabase/serverless |
| Traditional Node.js | pg | npm install pg |
| Long-running servers | pg with pooling | npm install pg |
For detailed serverless driver usage, see neon-serverless.md. For complex scenarios (multiple runtimes, hybrid architectures), reference connection-methods.md.
Step 4: Understand the Project
If it's an empty/new project: Ask briefly (1-2 questions):
- What are they building?
- Any specific technologies?
If it's an established project: Skip questions - infer from codebase. Update relevant code to use the driver.
Step 5: Authentication (Optional)
Skip if project doesn't need auth (CLI tools, scripts, static sites).
If project could benefit from auth: Ask: "Does your app need user authentication? Neon Auth can handle sign-in/sign-up, social login, and session management."
If they want auth:
- Use MCP server
provision_neon_authtool - Guide through framework-specific setup
- Configure environment variables
- Set up basic auth code
For detailed auth setup, see neon-auth.md. For auth + database queries, see neon-js.md.
Step 6: ORM Setup
Check for existing ORM (Prisma, Drizzle, TypeORM).
If no ORM found: Ask: "Want to set up an ORM for type-safe database queries?"
If yes, suggest based on project. If no, proceed with raw SQL.
For Drizzle ORM integration, see neon-drizzle.md.
Step 7: Schema Setup
Check for existing schema:
- SQL migration files
- ORM schemas (Prisma, Drizzle)
- Database initialization scripts
If existing schema found: Ask: "Found existing schema definitions. Want to migrate these to your Neon database?"
If no schema: Ask if they want to:
1. Create a simple example schema (users table) 2. Design a custom schema together 3. Skip schema setup for now
Example schema:
CREATE TABLE users (
id SERIAL PRIMARY KEY,
email VARCHAR(255) UNIQUE NOT NULL,
name VARCHAR(255),
created_at TIMESTAMP DEFAULT NOW()
);Step 8: What's Next
"You're all set! Here are some things I can help with:
- Neon-specific features (branching, autoscaling, scale-to-zero)
- Connection pooling for production
- Writing queries or building API endpoints
- Database migrations and schema changes
- Performance optimization"
Security Best Practices
1. Never commit connection strings to version control 2. Use environment variables for all credentials 3. Prefer SSL connections (default in Neon) 4. Use least-privilege database roles 5. Rotate API keys and passwords regularly
Resume Support
If user says "Continue with Neon setup", check what's already configured:
- MCP server connection
- .env file with DATABASE_URL
- Dependencies installed
- Schema created
Then resume from where they left off.
Developer Tools
For the best development experience, set up Neon's developer tools:
npx neon initThis installs the VSCode extension and configures the MCP server for AI-assisted development.
For detailed setup instructions, see devtools.md.
Documentation Resources
| Topic | URL |
|---|---|
| Getting Started | https://neon.tech/docs/get-started/signing-up |
| Connecting to Neon | https://neon.tech/docs/connect/connect-intro |
| Connection String | https://neon.tech/docs/connect/connect-from-any-app |
| Frameworks Guide | https://neon.tech/docs/get-started/frameworks |
| ORMs Guide | https://neon.tech/docs/get-started/orms |
| VSCode Extension | https://neon.tech/docs/local/vscode-extension |
| MCP Server | https://neon.tech/docs/ai/neon-mcp-server |
Neon Auth
Neon Auth provides authentication for your application. It's available as:
@neondatabase/auth- Auth only (smaller bundle)@neondatabase/neon-js- Auth + Data API (full SDK, seeneon-js.md)
For official documentation:
curl -H "Accept: text/markdown" https://neon.tech/docs/auth/overviewPackage Selection
| Need | Package | Bundle |
|---|---|---|
| Auth only | @neondatabase/auth | Smaller |
| Auth + Database queries | @neondatabase/neon-js | Full |
Installation
# Auth only
npm install @neondatabase/auth
# Auth + Data API
npm install @neondatabase/neon-jsQuick Setup Patterns
Next.js App Router
1. API Route Handler:
// app/api/auth/[...path]/route.ts
import { authApiHandler } from "@neondatabase/auth/next";
export const { GET, POST } = authApiHandler();2. Auth Client:
// lib/auth/client.ts
import { createAuthClient } from "@neondatabase/auth/next";
export const authClient = createAuthClient();3. Use in Components:
"use client";
import { authClient } from "@/lib/auth/client";
function AuthStatus() {
const session = authClient.useSession();
if (session.isPending) return <div>Loading...</div>;
if (!session.data) return <SignInButton />;
return <div>Hello, {session.data.user.name}</div>;
}React SPA
import { createAuthClient } from "@neondatabase/auth";
import { BetterAuthReactAdapter } from "@neondatabase/auth/react/adapters";
const authClient = createAuthClient(import.meta.env.VITE_NEON_AUTH_URL, {
adapter: BetterAuthReactAdapter(),
});Node.js Backend
import { createAuthClient } from "@neondatabase/auth";
const auth = createAuthClient(process.env.NEON_AUTH_URL!);
await auth.signIn.email({ email, password });
const session = await auth.getSession();Environment Variables
# Next.js (.env.local)
NEON_AUTH_BASE_URL=https://ep-xxx.neonauth.c-2.us-east-2.aws.neon.build/dbname/auth
NEXT_PUBLIC_NEON_AUTH_URL=https://ep-xxx.neonauth.c-2.us-east-2.aws.neon.build/dbname/auth
# Vite/React (.env)
VITE_NEON_AUTH_URL=https://ep-xxx.neonauth.c-2.us-east-2.aws.neon.build/dbname/authSub-Resources
For detailed documentation:
| Topic | Resource |
|---|---|
| Next.js App Router setup | neon-auth/setup-nextjs.md |
| React SPA setup | neon-auth/setup-react-spa.md |
| Auth methods reference | neon-auth/auth-methods.md |
| UI components | neon-auth/ui-components.md |
| Common mistakes | neon-auth/common-mistakes.md |
Key Imports
// Auth client (Next.js)
import { authApiHandler, createAuthClient } from "@neondatabase/auth/next";
// Auth client (vanilla)
import { createAuthClient } from "@neondatabase/auth";
// React adapter (NOT from main entry)
import { BetterAuthReactAdapter } from "@neondatabase/auth/react/adapters";
// UI components
import {
NeonAuthUIProvider,
AuthView,
SignInForm,
} from "@neondatabase/auth/react/ui";
import { authViewPaths } from "@neondatabase/auth/react/ui/server";
// CSS
import "@neondatabase/auth/ui/css";Common Mistakes
1. Wrong adapter import: Import BetterAuthReactAdapter from auth/react/adapters subpath 2. Forgetting to call adapter: Use BetterAuthReactAdapter() with parentheses 3. Missing CSS: Import from ui/css or ui/tailwind (not both) 4. Missing "use client": Required for components using useSession() 5. Wrong createAuthClient signature: First arg is URL: createAuthClient(url, { adapter })
See neon-auth/common-mistakes.md for detailed examples.
Neon Auth - Auth Methods Reference
Complete reference for authentication methods, session management, and error handling.
Auth Methods
Sign Up
await auth.signUp.email({
email: "user@example.com",
password: "securepassword",
name: "John Doe", // Optional
});Sign In
// Email/password
await auth.signIn.email({
email: "user@example.com",
password: "securepassword",
});
// Social (Google, GitHub)
await auth.signIn.social({
provider: "google", // or "github"
callbackURL: "/dashboard",
});Sign Out
await auth.signOut();Get Session
// Async (Node.js, server components)
const session = await auth.getSession();
// React hook (client components)
const session = auth.useSession();
// Returns: { data: Session | null, isPending: boolean }Session Data Structure
interface Session {
user: {
id: string;
name: string | null;
email: string;
image: string | null;
emailVerified: boolean;
createdAt: Date;
updatedAt: Date;
};
session: {
id: string;
expiresAt: Date;
token: string;
createdAt: Date;
updatedAt: Date;
userId: string;
};
}Error Handling
const { error } = await auth.signIn.email({ email, password });
if (error) {
switch (error.code) {
case "INVALID_EMAIL_OR_PASSWORD":
showError("Invalid email or password");
break;
case "EMAIL_NOT_VERIFIED":
showError("Please verify your email");
break;
case "USER_NOT_FOUND":
showError("User not found");
break;
case "TOO_MANY_REQUESTS":
showError("Too many attempts. Please wait.");
break;
default:
showError("Authentication failed");
}
}Building Auth Pages
Use AuthView (Recommended for React Apps)
For authentication pages, use the pre-built AuthView component instead of building custom forms.
What AuthView provides:
- Sign-in, sign-up, password reset, magic link pages
- Social providers (Google, GitHub) - requires TWO configurations: enable in Neon Console AND add
socialprop to NeonAuthUIProvider - Form validation, error handling, loading states
- Consistent styling via CSS variables
Setup (Next.js App Router):
1. Import CSS (in app/layout.tsx or app/globals.css):
import "@neondatabase/auth/ui/css";2. Wrap app with provider (create app/auth-provider.tsx):
"use client";
import { NeonAuthUIProvider } from "@neondatabase/auth/react/ui";
import { authClient } from "@/lib/auth/client";
import { useRouter } from "next/navigation";
import Link from "next/link";
export function AuthProvider({ children }: { children: React.ReactNode }) {
const router = useRouter();
return (
<NeonAuthUIProvider
authClient={authClient}
navigate={router.push}
replace={router.replace}
onSessionChange={() => router.refresh()}
Link={Link}
>
{children}
</NeonAuthUIProvider>
);
}3. Create auth page (app/auth/[path]/page.tsx):
import { AuthView } from "@neondatabase/auth/react/ui";
import { authViewPaths } from "@neondatabase/auth/react/ui/server";
export function generateStaticParams() {
return Object.values(authViewPaths).map((path) => ({ path }));
}
export default async function AuthPage({
params,
}: {
params: Promise<{ path: string }>;
}) {
const { path } = await params;
return <AuthView pathname={path} />;
}Result: You now have /auth/sign-in, /auth/sign-up, /auth/forgot-password, etc.
Available paths: "sign-in", "sign-up", "forgot-password", "reset-password", "magic-link", "two-factor", "callback", "sign-out"
When to Use Low-Level Methods Instead
Use authClient.signIn.email(), authClient.signUp.email() directly if:
- Node.js backend - No React, server-side auth only
- Custom design system - Your design team provides form components
- Mobile/CLI apps - Non-web frontends
- Headless auth - Testing or non-standard flows
For standard React web apps, use AuthView.
Common Anti-Pattern
// ❌ Don't build custom forms unless you have specific requirements
function CustomSignInPage() {
const [email, setEmail] = useState("");
const [password, setPassword] = useState("");
const [error, setError] = useState("");
const [loading, setLoading] = useState(false);
const handleSubmit = async (e) => {
e.preventDefault();
setLoading(true);
const { error } = await authClient.signIn.email({ email, password });
if (error) setError(error.message);
setLoading(false);
};
// ... 50+ more lines of form JSX, validation, error display
}
// ✅ Use AuthView instead - one component handles everything
<AuthView pathname="sign-in" />;Styling
Neon Auth UI automatically inherits your app's existing theme. If you have CSS variables like --primary, --background, etc. defined (from Tailwind, shadcn/ui, or custom CSS), auth components use them with no configuration.
Key features:
- Automatic inheritance: Uses your existing
--primary,--background, etc. - No conflicts: Auth styles are in
@layer neon-auth, so your styles always win - Import order doesn't matter: CSS layers handle priority automatically
Integration with shadcn/ui
If you use shadcn/ui or similar libraries that define --primary, --background, etc., Neon Auth will automatically inherit those colors. No additional configuration needed.
Use Existing CSS Variables
When creating custom components, use CSS variables for consistency:
| Variable | Purpose |
|---|---|
--background, --foreground | Page background/text |
--card, --card-foreground | Card surfaces |
--primary, --primary-foreground | Primary buttons/actions |
--muted, --muted-foreground | Muted/subtle elements |
--border, --ring | Borders and focus rings |
--radius | Border radius |
Auth-Specific Customization
To customize auth components differently from your main app, use --neon-* prefix:
:root {
--primary: oklch(0.55 0.25 250); /* Your app's blue */
--neon-primary: oklch(0.55 0.18 145); /* Auth uses green */
}Neon Auth - Common Mistakes
Reference guide for common mistakes when using @neondatabase/auth or @neondatabase/neon-js.
Import Mistakes
BetterAuthReactAdapter Subpath Requirement
BetterAuthReactAdapter is NOT exported from the main package entry. You must import it from the subpath.
Wrong:
// These will NOT work
import { BetterAuthReactAdapter } from "@neondatabase/neon-js";
import { BetterAuthReactAdapter } from "@neondatabase/auth";Correct:
// For @neondatabase/neon-js
import { BetterAuthReactAdapter } from "@neondatabase/neon-js/auth/react/adapters";
// For @neondatabase/auth
import { BetterAuthReactAdapter } from "@neondatabase/auth/react/adapters";Why: The React adapter has React-specific dependencies and is tree-shaken out of the main bundle. Using subpath exports keeps the main bundle smaller for non-React environments.
Adapter Factory Functions
All adapters are factory functions that must be called with ().
Wrong:
const client = createClient({
auth: {
adapter: BetterAuthReactAdapter, // Missing ()
url: process.env.NEON_AUTH_URL!,
},
dataApi: { url: process.env.NEON_DATA_API_URL! },
});Correct:
const client = createClient({
auth: {
adapter: BetterAuthReactAdapter(), // Called as function
url: process.env.NEON_AUTH_URL!,
},
dataApi: { url: process.env.NEON_DATA_API_URL! },
});This applies to all adapters:
BetterAuthReactAdapter()BetterAuthVanillaAdapter()SupabaseAuthAdapter()
---
CSS Import Mistakes
Auth UI components require CSS. Choose ONE method based on your project.
With Tailwind v4
/* In app/globals.css */
@import "tailwindcss";
@import "@neondatabase/neon-js/ui/tailwind";
/* Or: @import '@neondatabase/auth/ui/tailwind'; */Without Tailwind
// In app/layout.tsx
import "@neondatabase/neon-js/ui/css";
// Or: import "@neondatabase/auth/ui/css";Never Import Both
Wrong:
/* Causes ~94KB of duplicate styles */
@import "@neondatabase/neon-js/ui/css";
@import "@neondatabase/neon-js/ui/tailwind";Why: The ui/css import includes pre-built CSS (~47KB). The ui/tailwind import provides Tailwind tokens (~2KB) that generate similar styles. Using both doubles your CSS bundle.
---
Configuration Mistakes
Wrong createAuthClient Signature
The createAuthClient function takes the URL as the first argument, not as a property in an options object.
Wrong:
// This will NOT work
createAuthClient({ baseURL: url });
createAuthClient({ url: myUrl });Correct:
// Vanilla client - URL as first arg
createAuthClient(url);
// With adapter - URL as first arg, options as second
createAuthClient(url, { adapter: BetterAuthReactAdapter() });
// Next.js client - no arguments (uses env vars automatically)
import { createAuthClient } from "@neondatabase/auth/next";
const authClient = createAuthClient();Missing Environment Variables
Required for Next.js:
# .env.local
NEON_AUTH_BASE_URL=https://ep-xxx.neonauth.c-2.us-east-2.aws.neon.build/dbname/auth
NEXT_PUBLIC_NEON_AUTH_URL=https://ep-xxx.neonauth.c-2.us-east-2.aws.neon.build/dbname/auth
# For neon-js (auth + data)
NEON_DATA_API_URL=https://ep-xxx.apirest.c-2.us-east-2.aws.neon.build/dbname/rest/v1Required for Vite/React SPA:
# .env
VITE_NEON_AUTH_URL=https://ep-xxx.neonauth.c-2.us-east-2.aws.neon.build/dbname/auth
VITE_NEON_DATA_API_URL=https://ep-xxx.apirest.c-2.us-east-2.aws.neon.build/dbname/rest/v1Important:
NEON_AUTH_BASE_URL- Server-side authNEXT_PUBLIC_*prefix - Required for client-side access in Next.jsVITE_*prefix - Required for client-side access in Vite- Restart dev server after adding env vars
---
Usage Mistakes
Missing "use client" Directive
Client components using useSession() need the "use client" directive.
Wrong:
// Missing directive - will cause hydration errors
import { authClient } from "@/lib/auth/client";
function AuthStatus() {
const session = authClient.useSession();
// ...
}Correct:
"use client";
import { authClient } from "@/lib/auth/client";
function AuthStatus() {
const session = authClient.useSession();
// ...
}Wrong API for Adapter
Each adapter has its own API style. Don't mix them.
Wrong - BetterAuth API with SupabaseAuthAdapter:
const client = createClient({
auth: { adapter: SupabaseAuthAdapter(), url },
dataApi: { url },
});
// This won't work with SupabaseAuthAdapter
await client.auth.signIn.email({ email, password });Correct - Supabase API with SupabaseAuthAdapter:
const client = createClient({
auth: { adapter: SupabaseAuthAdapter(), url },
dataApi: { url },
});
// Use Supabase-style methods
await client.auth.signInWithPassword({ email, password });API Reference by Adapter:
| Adapter | Sign In | Sign Up | Get Session |
|---|---|---|---|
| BetterAuthVanillaAdapter | signIn.email({ email, password }) | signUp.email({ email, password }) | getSession() |
| BetterAuthReactAdapter | signIn.email({ email, password }) | signUp.email({ email, password }) | useSession() / getSession() |
| SupabaseAuthAdapter | signInWithPassword({ email, password }) | signUp({ email, password }) | getSession() |
Neon Auth Setup - Next.js App Router
Complete setup instructions for Neon Auth in Next.js App Router applications.
---
1. Install Package
npm install @neondatabase/auth
# Or: npm install @neondatabase/neon-js2. Environment Variables
Create or update .env.local:
NEON_AUTH_BASE_URL=https://ep-xxx.neonauth.c-2.us-east-2.aws.neon.build/dbname/auth
NEXT_PUBLIC_NEON_AUTH_URL=https://ep-xxx.neonauth.c-2.us-east-2.aws.neon.build/dbname/authImportant: Both variables are needed:
NEON_AUTH_BASE_URL- Used by server-side API routesNEXT_PUBLIC_NEON_AUTH_URL- Used by client-side components (prefixed with NEXTPUBLIC)
Where to find your Auth URL:
1. Go to your Neon project dashboard 2. Navigate to the "Auth" tab 3. Copy the Auth URL
3. API Route Handler
Create app/api/auth/[...path]/route.ts:
import { authApiHandler } from "@neondatabase/auth/next";
// Or: import { authApiHandler } from "@neondatabase/neon-js/auth/next";
export const { GET, POST } = authApiHandler();This creates endpoints for:
/api/auth/sign-in- Sign in/api/auth/sign-up- Sign up/api/auth/sign-out- Sign out/api/auth/session- Get session- And other auth-related endpoints
4. Auth Client Configuration
Create lib/auth/client.ts:
import { createAuthClient } from "@neondatabase/auth/next";
// Or: import { createAuthClient } from "@neondatabase/neon-js/auth/next";
export const authClient = createAuthClient();5. Use in Components
"use client";
import { authClient } from "@/lib/auth/client";
function AuthStatus() {
const session = authClient.useSession();
if (session.isPending) return <div>Loading...</div>;
if (!session.data) return <SignInButton />;
return (
<div>
<p>Hello, {session.data.user.name}</p>
<button onClick={() => authClient.signOut()}>Sign Out</button>
</div>
);
}
function SignInButton() {
return (
<button onClick={() => authClient.signIn.email({
email: "user@example.com",
password: "password"
})}>
Sign In
</button>
);
}6. UI Provider Setup (Optional)
For pre-built UI components (AuthView, UserButton, etc.), see ui-components.md.
---
Package Selection
| Need | Package | Bundle Size |
|---|---|---|
| Auth only | @neondatabase/auth | Smaller (~50KB) |
| Auth + Database queries | @neondatabase/neon-js | Full (~150KB) |
Recommendation: Use @neondatabase/auth if you only need authentication. Use @neondatabase/neon-js if you also need PostgREST-style database queries.
Neon Auth Setup - React SPA (Vite)
Complete setup instructions for Neon Auth in React Single Page Applications (Vite, Create React App, etc.).
---
1. Install Package
npm install @neondatabase/auth
# Or: npm install @neondatabase/neon-js
npm install react-router-dom # Required for UI components2. Environment Variables
Create or update .env:
For Vite:
VITE_NEON_AUTH_URL=https://ep-xxx.neonauth.c-2.us-east-2.aws.neon.build/dbname/authFor Create React App:
REACT_APP_NEON_AUTH_URL=https://ep-xxx.neonauth.c-2.us-east-2.aws.neon.build/dbname/authWhere to find your Auth URL:
1. Go to your Neon project dashboard 2. Navigate to the "Auth" tab 3. Copy the Auth URL
3. Auth Client Configuration
Create src/lib/auth-client.ts:
For `@neondatabase/auth`:
import { createAuthClient } from "@neondatabase/auth";
import { BetterAuthReactAdapter } from "@neondatabase/auth/react/adapters";
export const authClient = createAuthClient(import.meta.env.VITE_NEON_AUTH_URL, {
adapter: BetterAuthReactAdapter(),
});For `@neondatabase/neon-js`:
import { createClient } from "@neondatabase/neon-js";
import { BetterAuthReactAdapter } from "@neondatabase/neon-js/auth/react/adapters";
export const client = createClient({
auth: {
adapter: BetterAuthReactAdapter(),
url: import.meta.env.VITE_NEON_AUTH_URL,
},
dataApi: {
url: import.meta.env.VITE_NEON_DATA_API_URL,
},
});
export const authClient = client.auth;Critical:
BetterAuthReactAdaptermust be imported from the/react/adapterssubpath- The adapter must be called as a function:
BetterAuthReactAdapter()
4. Use in Components
import { authClient } from "./lib/auth-client";
function App() {
const session = authClient.useSession();
if (session.isPending) return <div>Loading...</div>;
if (!session.data) return <LoginForm />;
return <Dashboard user={session.data.user} />;
}---
5. UI Provider Setup (Optional)
Skip this section if you're building custom auth forms. Use this if you want pre-built UI components.
5a. Import CSS
CRITICAL: Choose ONE import method. Never import both - it causes duplicate styles.
Check if the project uses Tailwind CSS by looking for:
tailwind.config.jsortailwind.config.tsin the project root@import 'tailwindcss'or@tailwinddirectives in CSS filestailwindcssin package.json dependencies
If NOT using Tailwind - Add to src/main.tsx or entry point:
import "@neondatabase/auth/ui/css";If using Tailwind CSS v4 - Add to main CSS file (e.g., index.css):
@import "tailwindcss";
@import "@neondatabase/auth/ui/tailwind";5b. Update main.tsx with BrowserRouter
import { createRoot } from "react-dom/client";
import { BrowserRouter } from "react-router-dom";
import "@neondatabase/auth/ui/css"; // if not using Tailwind
import App from "./App";
import { Providers } from "./providers";
createRoot(document.getElementById("root")!).render(
<BrowserRouter>
<Providers>
<App />
</Providers>
</BrowserRouter>,
);5c. Create Auth Provider
Create src/providers.tsx:
import { NeonAuthUIProvider } from "@neondatabase/auth/react/ui";
import { useNavigate, Link as RouterLink } from "react-router-dom";
import { authClient } from "./lib/auth-client";
import type { ReactNode } from "react";
// Adapter for react-router-dom Link
function Link({
href,
...props
}: { href: string } & React.AnchorHTMLAttributes<HTMLAnchorElement>) {
return <RouterLink to={href} {...props} />;
}
export function Providers({ children }: { children: ReactNode }) {
const navigate = useNavigate();
return (
<NeonAuthUIProvider
authClient={authClient}
navigate={(path) => navigate(path)}
replace={(path) => navigate(path, { replace: true })}
onSessionChange={() => {
// Optional: refresh data or invalidate cache
}}
Link={Link}
social={{
providers: ["google", "github"],
}}
>
{children}
</NeonAuthUIProvider>
);
}Provider props explained:
navigate: Function to navigate to a new routereplace: Function to replace current route (for redirects)onSessionChange: Callback when auth state changes (useful for cache invalidation)Link: Adapter component for react-router-dom's Linksocial: Show Google and GitHub sign-in buttons (both enabled by default in Neon)
5d. Add Routes to App.tsx
import { Routes, Route, useParams } from "react-router-dom";
import {
AuthView,
UserButton,
SignedIn,
SignedOut,
} from "@neondatabase/auth/react/ui";
// Auth page - handles /auth/sign-in, /auth/sign-up, etc.
function AuthPage() {
const { pathname } = useParams();
return (
<div className="flex min-h-screen items-center justify-center">
<AuthView pathname={pathname} />
</div>
);
}
// Simple navbar example
function Navbar() {
return (
<nav className="flex items-center justify-between p-4 border-b">
<a href="/">My App</a>
<div className="flex items-center gap-4">
<SignedOut>
<a href="/auth/sign-in">Sign In</a>
</SignedOut>
<SignedIn>
<UserButton />
</SignedIn>
</div>
</nav>
);
}
function HomePage() {
return <div>Welcome to My App!</div>;
}
export default function App() {
return (
<>
<Navbar />
<Routes>
<Route path="/" element={<HomePage />} />
<Route path="/auth/:pathname" element={<AuthPage />} />
</Routes>
</>
);
}Auth routes created:
/auth/sign-in- Sign in page/auth/sign-up- Sign up page/auth/forgot-password- Password reset request/auth/reset-password- Set new password/auth/sign-out- Sign out/auth/callback- OAuth callback (internal)
Neon Auth - UI Components Reference
Pre-built UI components for authentication flows.
Available Components
AuthView- Complete auth pages (sign-in, sign-up, forgot-password, etc.) - use this firstSignedIn/SignedOut- Conditional rendering based on auth stateUserButton- User avatar with dropdown menuNeonAuthUIProvider- Required wrapper for UI components
CSS Import
CRITICAL: Choose ONE import method. Never import both.
Without Tailwind:
// In app/layout.tsx or entry point
import "@neondatabase/auth/ui/css";With Tailwind v4:
/* In app/globals.css */
@import "tailwindcss";
@import "@neondatabase/auth/ui/tailwind";NeonAuthUIProvider Setup
Next.js App Router
"use client";
import { NeonAuthUIProvider } from "@neondatabase/auth/react/ui";
import { authClient } from "@/lib/auth/client";
import { useRouter } from "next/navigation";
import Link from "next/link";
export function AuthProvider({ children }: { children: React.ReactNode }) {
const router = useRouter();
return (
<NeonAuthUIProvider
authClient={authClient}
navigate={router.push}
replace={router.replace}
onSessionChange={() => router.refresh()}
Link={Link}
social={{
providers: ["google", "github"],
}}
>
{children}
</NeonAuthUIProvider>
);
}React SPA with react-router-dom
import { NeonAuthUIProvider } from "@neondatabase/auth/react/ui";
import { useNavigate, Link as RouterLink } from "react-router-dom";
import { authClient } from "./lib/auth-client";
function Link({
href,
...props
}: { href: string } & React.AnchorHTMLAttributes<HTMLAnchorElement>) {
return <RouterLink to={href} {...props} />;
}
export function Providers({ children }: { children: React.ReactNode }) {
const navigate = useNavigate();
return (
<NeonAuthUIProvider
authClient={authClient}
navigate={(path) => navigate(path)}
replace={(path) => navigate(path, { replace: true })}
onSessionChange={() => {}}
Link={Link}
social={{
providers: ["google", "github"],
}}
>
{children}
</NeonAuthUIProvider>
);
}AuthView Component
Renders complete authentication pages.
Next.js App Router
Create app/auth/[path]/page.tsx:
import { AuthView } from "@neondatabase/auth/react/ui";
import { authViewPaths } from "@neondatabase/auth/react/ui/server";
export function generateStaticParams() {
return Object.values(authViewPaths).map((path) => ({ path }));
}
export default async function AuthPage({
params,
}: {
params: Promise<{ path: string }>;
}) {
const { path } = await params;
return <AuthView pathname={path} />;
}React SPA
import { Routes, Route, useParams } from "react-router-dom";
import { AuthView } from "@neondatabase/auth/react/ui";
function AuthPage() {
const { pathname } = useParams();
return (
<div className="flex min-h-screen items-center justify-center">
<AuthView pathname={pathname} />
</div>
);
}
export default function App() {
return (
<Routes>
<Route path="/" element={<HomePage />} />
<Route path="/auth/:pathname" element={<AuthPage />} />
</Routes>
);
}Available Auth Paths
| Path | Purpose |
|---|---|
sign-in | Sign in page |
sign-up | Sign up page |
forgot-password | Password reset request |
reset-password | Set new password |
magic-link | Magic link sign in |
two-factor | Two-factor authentication |
callback | OAuth callback (internal) |
sign-out | Sign out |
SignedIn / SignedOut Components
Conditional rendering based on authentication state.
import { SignedIn, SignedOut, UserButton } from "@neondatabase/auth/react/ui";
function Navbar() {
return (
<nav>
<SignedOut>
<a href="/auth/sign-in">Sign In</a>
<a href="/auth/sign-up">Sign Up</a>
</SignedOut>
<SignedIn>
<UserButton />
</SignedIn>
</nav>
);
}UserButton Component
Displays user avatar with dropdown menu for account management.
import { UserButton } from "@neondatabase/auth/react/ui";
function Header() {
return (
<header>
<h1>My App</h1>
<UserButton />
</header>
);
}Social Login Configuration
Important: Social providers require TWO configurations:
1. Enable in Neon Console - Go to your project's Auth settings 2. Add to NeonAuthUIProvider - Pass social prop
<NeonAuthUIProvider
authClient={authClient}
// ... other props
social={{
providers: ['google', 'github']
}}
>Without both configurations, social login buttons won't appear.
Neon CLI
The Neon CLI is a command-line interface for managing Neon Serverless Postgres directly from your terminal. It provides the same capabilities as the Neon Platform API and is ideal for scripting, CI/CD pipelines, and developers who prefer terminal workflows.
Installation
macOS (Homebrew):
brew install neonctlnpm (cross-platform):
npm install -g neonctlDirect download:
curl -fsSL https://neon.tech/install.sh | bashAuthentication
Authenticate with your Neon account:
neonctl authThis opens a browser for OAuth authentication and stores credentials locally.
For CI/CD or non-interactive environments, use an API key:
export NEON_API_KEY=your-api-keyGet your API key from: https://console.neon.tech/app/settings/api-keys
Common Commands
Project Management
# List all projects
neonctl projects list
# Create a new project
neonctl projects create --name my-project
# Get project details
neonctl projects get <project-id>
# Delete a project
neonctl projects delete <project-id>Branch Operations
# List branches
neonctl branches list --project-id <project-id>
# Create a branch
neonctl branches create --project-id <project-id> --name dev
# Delete a branch
neonctl branches delete <branch-id> --project-id <project-id>Connection Strings
# Get connection string
neonctl connection-string --project-id <project-id>
# Get connection string for specific branch
neonctl connection-string --project-id <project-id> --branch-id <branch-id>
# Get pooled connection string
neonctl connection-string --project-id <project-id> --pooledSQL Execution
# Run SQL query
neonctl sql "SELECT * FROM users LIMIT 10" --project-id <project-id>
# Run SQL from file
neonctl sql --file schema.sql --project-id <project-id>Database Management
# List databases
neonctl databases list --project-id <project-id> --branch-id <branch-id>
# Create database
neonctl databases create --project-id <project-id> --name mydb
# List roles
neonctl roles list --project-id <project-id> --branch-id <branch-id>Output Formats
The CLI supports multiple output formats:
# JSON output (default for scripting)
neonctl projects list --output json
# Table output (human-readable)
neonctl projects list --output table
# YAML output
neonctl projects list --output yamlCI/CD Integration
Example GitHub Actions workflow:
- name: Create preview branch
env:
NEON_API_KEY: ${{ secrets.NEON_API_KEY }}
run: |
neonctl branches create \
--project-id ${{ vars.NEON_PROJECT_ID }} \
--name preview-${{ github.event.pull_request.number }}CLI vs MCP Server vs SDKs
| Tool | Best For |
|---|---|
| Neon CLI | Terminal workflows, scripts, CI/CD pipelines |
| MCP Server | AI-assisted development with Claude, Cursor, etc. |
| TypeScript SDK | Programmatic access in Node.js/TypeScript apps |
| Python SDK | Programmatic access in Python applications |
| REST API | Direct HTTP integration in any language |
Documentation Resources
| Topic | URL |
|---|---|
| CLI Reference | https://neon.tech/docs/reference/neon-cli |
| CLI Install | https://neon.tech/docs/reference/cli-install |
| CLI Auth | https://neon.tech/docs/reference/cli-auth |
| CLI Projects | https://neon.tech/docs/reference/cli-projects |
| CLI Branches | https://neon.tech/docs/reference/cli-branches |
| CLI Connection | https://neon.tech/docs/reference/cli-connection-string |
Fetch CLI documentation:
curl -H "Accept: text/markdown" https://neon.tech/docs/reference/neon-cliNeon and Drizzle Integration
Integration patterns, configurations, and optimizations for using Drizzle ORM with Neon Postgres.
For official documentation:
curl -H "Accept: text/markdown" https://neon.tech/docs/guides/drizzleChoosing the Right Driver
Drizzle ORM works with multiple Postgres drivers. See connection-methods.md for the full decision tree.
| Platform | TCP Support | Pooling | Recommended Driver |
|---|---|---|---|
| Vercel (Fluid) | Yes | @vercel/functions | pg (node-postgres) |
| Cloudflare (Hyperdrive) | Yes | Hyperdrive | pg (node-postgres) |
| Cloudflare Workers | No | No | @neondatabase/serverless |
| Netlify Functions | No | No | @neondatabase/serverless |
| Deno Deploy | No | No | @neondatabase/serverless |
| Railway / Render | Yes | Built-in | pg (node-postgres) |
Connection Setup
1. TCP with node-postgres (Long-Running Servers)
Best for Railway, Render, traditional VPS.
npm install drizzle-orm pg
npm install -D drizzle-kit @types/pg dotenv// src/db.ts
import { drizzle } from "drizzle-orm/node-postgres";
import { Pool } from "pg";
const pool = new Pool({ connectionString: process.env.DATABASE_URL });
export const db = drizzle({ client: pool });2. Vercel Fluid Compute with Connection Pooling
npm install drizzle-orm pg @vercel/functions
npm install -D drizzle-kit @types/pg// src/db.ts
import { attachDatabasePool } from "@vercel/functions";
import { drizzle } from "drizzle-orm/node-postgres";
import { Pool } from "pg";
import * as schema from "./schema";
const pool = new Pool({ connectionString: process.env.DATABASE_URL });
attachDatabasePool(pool);
export const db = drizzle({ client: pool, schema });3. HTTP Adapter (Edge Without TCP)
For Cloudflare Workers, Netlify Edge, Deno Deploy. Does NOT support interactive transactions.
npm install drizzle-orm @neondatabase/serverless
npm install -D drizzle-kit dotenv// src/db.ts
import { drizzle } from "drizzle-orm/neon-http";
import { neon } from "@neondatabase/serverless";
const sql = neon(process.env.DATABASE_URL!);
export const db = drizzle(sql);4. WebSocket Adapter (Edge with Transactions)
npm install drizzle-orm @neondatabase/serverless ws
npm install -D drizzle-kit dotenv @types/ws// src/db.ts
import { drizzle } from "drizzle-orm/neon-serverless";
import { Pool, neonConfig } from "@neondatabase/serverless";
import ws from "ws";
neonConfig.webSocketConstructor = ws; // Required for Node.js < v22
const pool = new Pool({ connectionString: process.env.DATABASE_URL });
export const db = drizzle(pool);Drizzle Config
// drizzle.config.ts
import { config } from "dotenv";
import { defineConfig } from "drizzle-kit";
config({ path: ".env.local" });
export default defineConfig({
schema: "./src/schema.ts",
out: "./drizzle",
dialect: "postgresql",
dbCredentials: {
url: process.env.DATABASE_URL!,
},
});Migrations
# Generate migrations
npx drizzle-kit generate
# Apply migrations
npx drizzle-kit migrateSchema Definition
// src/schema.ts
import { pgTable, serial, text, integer, timestamp } from "drizzle-orm/pg-core";
export const usersTable = pgTable("users", {
id: serial("id").primaryKey(),
name: text("name").notNull(),
email: text("email").notNull().unique(),
role: text("role").default("user").notNull(),
createdAt: timestamp("created_at").defaultNow().notNull(),
});
export type User = typeof usersTable.$inferSelect;
export type NewUser = typeof usersTable.$inferInsert;
export const postsTable = pgTable("posts", {
id: serial("id").primaryKey(),
title: text("title").notNull(),
content: text("content").notNull(),
userId: integer("user_id")
.notNull()
.references(() => usersTable.id, { onDelete: "cascade" }),
createdAt: timestamp("created_at").defaultNow().notNull(),
});
export type Post = typeof postsTable.$inferSelect;
export type NewPost = typeof postsTable.$inferInsert;Query Patterns
Batch Inserts
export async function batchInsertUsers(users: NewUser[]) {
return db.insert(usersTable).values(users).returning();
}Prepared Statements
import { sql } from "drizzle-orm";
export const getUsersByRolePrepared = db
.select()
.from(usersTable)
.where(sql`${usersTable.role} = $1`)
.prepare("get_users_by_role");
// Usage: getUsersByRolePrepared.execute(['admin'])Transactions
export async function createUserWithPosts(user: NewUser, posts: NewPost[]) {
return await db.transaction(async (tx) => {
const [newUser] = await tx.insert(usersTable).values(user).returning();
if (posts.length > 0) {
await tx.insert(postsTable).values(
posts.map((post) => ({
...post,
userId: newUser.id,
})),
);
}
return newUser;
});
}Working with Neon Branches
import { drizzle } from "drizzle-orm/neon-http";
import { neon } from "@neondatabase/serverless";
const getBranchUrl = () => {
const env = process.env.NODE_ENV;
if (env === "development") return process.env.DEV_DATABASE_URL;
if (env === "test") return process.env.TEST_DATABASE_URL;
return process.env.DATABASE_URL;
};
const sql = neon(getBranchUrl()!);
export const db = drizzle({ client: sql });Error Handling
export async function safeNeonOperation<T>(
operation: () => Promise<T>,
): Promise<T> {
try {
return await operation();
} catch (error: any) {
if (error.message?.includes("connection pool timeout")) {
console.error("Neon connection pool timeout");
}
throw error;
}
}Best Practices
1. Connection Management - See connection-methods.md for platform-specific guidance 2. Neon Features - Utilize branching for development/testing (see features.md) 3. Query Optimization - Batch operations, use prepared statements 4. Schema Design - Leverage Postgres-specific features, use appropriate indexes
Neon JS SDK
The @neondatabase/neon-js SDK provides a unified client for Neon Auth and Data API. It combines authentication handling with PostgREST-compatible database queries.
Auth only? Use neon-auth.md instead for smaller bundle size.
For official documentation:
curl -H "Accept: text/markdown" https://neon.tech/docs/reference/javascript-sdkPackage Selection
| Use Case | Package | Notes |
|---|---|---|
| Auth + Data API | @neondatabase/neon-js | Full SDK |
| Auth only | @neondatabase/auth | Smaller bundle |
| Data API only | @neondatabase/postgrest-js | Bring your own auth |
Installation
npm install @neondatabase/neon-jsQuick Setup Patterns
Next.js (Most Common)
1. API Route Handler:
// app/api/auth/[...path]/route.ts
import { authApiHandler } from "@neondatabase/neon-js/auth/next";
export const { GET, POST } = authApiHandler();2. Auth Client:
// lib/auth/client.ts
import { createAuthClient } from "@neondatabase/neon-js/auth/next";
export const authClient = createAuthClient();3. Database Client:
// lib/db/client.ts
import { createClient } from "@neondatabase/neon-js";
import type { Database } from "./database.types";
export const dbClient = createClient<Database>({
auth: { url: process.env.NEXT_PUBLIC_NEON_AUTH_URL! },
dataApi: { url: process.env.NEON_DATA_API_URL! },
});React SPA
import { createClient } from "@neondatabase/neon-js";
import { BetterAuthReactAdapter } from "@neondatabase/neon-js/auth/react/adapters";
const client = createClient<Database>({
auth: {
adapter: BetterAuthReactAdapter(),
url: import.meta.env.VITE_NEON_AUTH_URL,
},
dataApi: { url: import.meta.env.VITE_NEON_DATA_API_URL },
});Node.js Backend
import { createClient } from "@neondatabase/neon-js";
const client = createClient<Database>({
auth: { url: process.env.NEON_AUTH_URL! },
dataApi: { url: process.env.NEON_DATA_API_URL! },
});Environment Variables
# Next.js (.env.local)
NEON_AUTH_BASE_URL=https://ep-xxx.neonauth.c-2.us-east-2.aws.neon.build/dbname/auth
NEXT_PUBLIC_NEON_AUTH_URL=https://ep-xxx.neonauth.c-2.us-east-2.aws.neon.build/dbname/auth
NEON_DATA_API_URL=https://ep-xxx.apirest.c-2.us-east-2.aws.neon.build/dbname/rest/v1
# Vite/React (.env)
VITE_NEON_AUTH_URL=https://ep-xxx.neonauth.c-2.us-east-2.aws.neon.build/dbname/auth
VITE_NEON_DATA_API_URL=https://ep-xxx.apirest.c-2.us-east-2.aws.neon.build/dbname/rest/v1Database Queries
All query methods follow PostgREST syntax (same as Supabase):
// Select with filters
const { data } = await client
.from("items")
.select("id, name, status")
.eq("status", "active")
.order("created_at", { ascending: false })
.limit(10);
// Insert
const { data, error } = await client
.from("items")
.insert({ name: "New Item", status: "pending" })
.select()
.single();
// Update
await client.from("items").update({ status: "completed" }).eq("id", 1);
// Delete
await client.from("items").delete().eq("id", 1);For complete Data API query reference, see neon-js/data-api.md.
Auth Methods
BetterAuth API (Default)
// Sign in/up
await client.auth.signIn.email({ email, password });
await client.auth.signUp.email({ email, password, name });
await client.auth.signOut();
// Get session
const session = await client.auth.getSession();
// Social sign-in
await client.auth.signIn.social({
provider: "google",
callbackURL: "/dashboard",
});Supabase-Compatible API
import { createClient, SupabaseAuthAdapter } from "@neondatabase/neon-js";
const client = createClient({
auth: { adapter: SupabaseAuthAdapter(), url },
dataApi: { url },
});
await client.auth.signInWithPassword({ email, password });
await client.auth.signUp({ email, password });
const {
data: { session },
} = await client.auth.getSession();Sub-Resources
| Topic | Resource |
|---|---|
| Data API queries | neon-js/data-api.md |
| Common mistakes | neon-js/common-mistakes.md |
Key Imports
// Main client
import {
createClient,
SupabaseAuthAdapter,
BetterAuthVanillaAdapter,
} from "@neondatabase/neon-js";
// Next.js integration
import {
authApiHandler,
createAuthClient,
} from "@neondatabase/neon-js/auth/next";
// React adapter (NOT from main entry - must use subpath)
import { BetterAuthReactAdapter } from "@neondatabase/neon-js/auth/react/adapters";
// UI components
import {
NeonAuthUIProvider,
AuthView,
SignInForm,
} from "@neondatabase/neon-js/auth/react/ui";
import { authViewPaths } from "@neondatabase/neon-js/auth/react/ui/server";
// CSS (choose one)
import "@neondatabase/neon-js/ui/css"; // Without Tailwind
// @import '@neondatabase/neon-js/ui/tailwind'; // With Tailwind v4 (in CSS file)Generate Types
npx neon-js gen-types --db-url "postgresql://..." --output src/types/database.tsCommon Mistakes
1. Wrong adapter import: Import BetterAuthReactAdapter from auth/react/adapters subpath 2. Forgetting to call adapter: Use SupabaseAuthAdapter() with parentheses 3. Missing CSS import: Import from ui/css or ui/tailwind (not both) 4. Wrong package for auth-only: Use @neondatabase/auth for smaller bundle 5. Missing "use client": Required for auth client components
See neon-js/common-mistakes.md for detailed examples.
Neon JS - Common Mistakes
Reference guide for common mistakes when using @neondatabase/neon-js.
Import Mistakes
BetterAuthReactAdapter Subpath Requirement
BetterAuthReactAdapter is NOT exported from the main package entry.
Wrong:
import { BetterAuthReactAdapter } from "@neondatabase/neon-js";Correct:
import { BetterAuthReactAdapter } from "@neondatabase/neon-js/auth/react/adapters";Adapter Factory Functions
All adapters must be called with ().
Wrong:
const client = createClient({
auth: {
adapter: BetterAuthReactAdapter, // Missing ()
url: process.env.NEON_AUTH_URL!,
},
dataApi: { url: process.env.NEON_DATA_API_URL! },
});Correct:
const client = createClient({
auth: {
adapter: BetterAuthReactAdapter(), // Called as function
url: process.env.NEON_AUTH_URL!,
},
dataApi: { url: process.env.NEON_DATA_API_URL! },
});---
CSS Import Mistakes
Choose ONE CSS import method:
With Tailwind v4:
@import "tailwindcss";
@import "@neondatabase/neon-js/ui/tailwind";Without Tailwind:
import "@neondatabase/neon-js/ui/css";Never import both - causes duplicate styles.
---
Environment Variables
Required for Next.js:
# .env.local
NEON_AUTH_BASE_URL=https://ep-xxx.neonauth.c-2.us-east-2.aws.neon.build/dbname/auth
NEXT_PUBLIC_NEON_AUTH_URL=https://ep-xxx.neonauth.c-2.us-east-2.aws.neon.build/dbname/auth
NEON_DATA_API_URL=https://ep-xxx.apirest.c-2.us-east-2.aws.neon.build/dbname/rest/v1Required for Vite/React SPA:
# .env
VITE_NEON_AUTH_URL=https://ep-xxx.neonauth.c-2.us-east-2.aws.neon.build/dbname/auth
VITE_NEON_DATA_API_URL=https://ep-xxx.apirest.c-2.us-east-2.aws.neon.build/dbname/rest/v1---
Usage Mistakes
Missing "use client" Directive
"use client"; // Required!
import { authClient } from "@/lib/auth/client";
function AuthStatus() {
const session = authClient.useSession();
// ...
}Wrong API for Adapter
| Adapter | Sign In | Sign Up |
|---|---|---|
| BetterAuthReactAdapter | signIn.email({ email, password }) | signUp.email({ email, password }) |
| SupabaseAuthAdapter | signInWithPassword({ email, password }) | signUp({ email, password }) |
Using neon-js for Auth Only
If you only need auth (no database queries), use @neondatabase/auth for smaller bundle size:
# Auth only - smaller bundle
npm install @neondatabase/auth
# Auth + Data API - full SDK
npm install @neondatabase/neon-jsNeon JS Data API Reference
Complete reference for PostgREST-style database queries using @neondatabase/neon-js.
Client Setup
Next.js
// lib/db/client.ts
import { createClient } from "@neondatabase/neon-js";
import type { Database } from "./database.types";
export const dbClient = createClient<Database>({
auth: { url: process.env.NEXT_PUBLIC_NEON_AUTH_URL! },
dataApi: { url: process.env.NEON_DATA_API_URL! },
});React SPA
import { createClient } from "@neondatabase/neon-js";
import { BetterAuthReactAdapter } from "@neondatabase/neon-js/auth/react/adapters";
const client = createClient<Database>({
auth: {
adapter: BetterAuthReactAdapter(),
url: import.meta.env.VITE_NEON_AUTH_URL,
},
dataApi: { url: import.meta.env.VITE_NEON_DATA_API_URL },
});Node.js Backend
import { createClient } from "@neondatabase/neon-js";
const client = createClient<Database>({
auth: { url: process.env.NEON_AUTH_URL! },
dataApi: { url: process.env.NEON_DATA_API_URL! },
});---
Query Patterns
All query methods follow PostgREST syntax (same as Supabase).
Select Queries
Basic select:
const { data, error } = await client.from("items").select();Select specific columns:
const { data } = await client.from("items").select("id, name, status");Select with filters:
const { data } = await client
.from("items")
.select("id, name, status")
.eq("status", "active")
.order("created_at", { ascending: false })
.limit(10);Select single row:
const { data, error } = await client
.from("items")
.select("*")
.eq("id", 1)
.single();Insert
Insert single row:
const { data, error } = await client
.from("items")
.insert({ name: "New Item", status: "pending" })
.select()
.single();Insert multiple rows:
const { data, error } = await client
.from("items")
.insert([
{ name: "Item 1", status: "pending" },
{ name: "Item 2", status: "pending" },
])
.select();Update
Update with filter:
await client.from("items").update({ status: "completed" }).eq("id", 1);Update and return data:
const { data, error } = await client
.from("items")
.update({ status: "completed" })
.eq("id", 1)
.select()
.single();Delete
Delete single row:
await client.from("items").delete().eq("id", 1);Delete and return data:
const { data, error } = await client
.from("items")
.delete()
.eq("id", 1)
.select()
.single();Upsert
await client
.from("items")
.upsert({ id: 1, name: "Updated Item", status: "active" });---
Filtering
Comparison Operators
// Equal
.eq("status", "active")
// Not equal
.neq("status", "archived")
// Greater than
.gt("price", 100)
// Greater than or equal
.gte("price", 100)
// Less than
.lt("price", 100)
// Less than or equal
.lte("price", 100)
// Like (pattern matching)
.like("name", "%item%")
// ILike (case-insensitive)
.ilike("name", "%item%")
// Is null
.is("deleted_at", null)
// Is not null
.not("deleted_at", "is", null)
// In array
.in("status", ["active", "pending"])
// Contains (for arrays/JSONB)
.contains("tags", ["important"])Logical Operators
// AND (chained)
.eq("status", "active")
.gt("price", 100)
// OR
.or("status.eq.active,price.gt.100")
// NOT
.not("status", "eq", "archived")Ordering
// Ascending
.order("created_at", { ascending: true })
// Descending
.order("created_at", { ascending: false })
// Multiple columns
.order("status", { ascending: true })
.order("created_at", { ascending: false })Pagination
// Limit
.limit(10)
// Range (offset + limit)
.range(0, 9) // First 10 items
// Range for pagination
const page = 1;
const pageSize = 10;
.range((page - 1) * pageSize, page * pageSize - 1)---
Relationships
Select with Relationships
One-to-many:
const { data } = await client
.from("posts")
.select("id, title, author:users(name, email)");Many-to-many:
const { data } = await client
.from("posts")
.select("id, title, tags:post_tags(tag:tags(name))");Nested relationships:
const { data } = await client.from("posts").select(`
id,
title,
author:users(
id,
name,
profile:profiles(bio, avatar)
)
`);---
Type Generation
Generate TypeScript types from your database schema:
npx neon-js gen-types --db-url "postgresql://user:pass@host/db" --output src/types/database.tsOr using environment variable:
npx neon-js gen-types --db-url "$DATABASE_URL" --output lib/db/database.types.tsUse types in client:
import { createClient } from "@neondatabase/neon-js";
import type { Database } from "./database.types";
export const dbClient = createClient<Database>({
auth: { url: process.env.NEXT_PUBLIC_NEON_AUTH_URL! },
dataApi: { url: process.env.NEON_DATA_API_URL! },
});Benefits:
- Full TypeScript autocomplete for tables and columns
- Type-safe queries
- Compile-time error checking
---
Error Handling
Check for errors:
const { data, error } = await client.from("items").select();
if (error) {
console.error("Database error:", error.message);
console.error("Error code:", error.code);
console.error("Error details:", error.details);
return;
}
// Use data
console.log(data);Common error codes:
PGRST116- No rows returned (when using.single())23505- Unique violation23503- Foreign key violation42P01- Table does not exist
---
Usage Examples
Server Component (Next.js)
// app/posts/page.tsx
import { dbClient } from "@/lib/db/client";
export default async function PostsPage() {
const { data: posts, error } = await dbClient
.from("posts")
.select("id, title, created_at, author:users(name)")
.order("created_at", { ascending: false })
.limit(10);
if (error) return <div>Error loading posts</div>;
return (
<ul>
{posts?.map((post) => (
<li key={post.id}>
<h2>{post.title}</h2>
<p>By {post.author?.name}</p>
</li>
))}
</ul>
);
}API Route (Next.js)
// app/api/posts/route.ts
import { dbClient } from "@/lib/db/client";
import { NextResponse } from "next/server";
export async function GET() {
const { data, error } = await dbClient.from("posts").select();
if (error) {
return NextResponse.json({ error: error.message }, { status: 500 });
}
return NextResponse.json(data);
}
export async function POST(request: Request) {
const body = await request.json();
const { data, error } = await dbClient
.from("posts")
.insert(body)
.select()
.single();
if (error) {
return NextResponse.json({ error: error.message }, { status: 400 });
}
return NextResponse.json(data, { status: 201 });
}Client Component (React)
"use client";
import { useEffect, useState } from "react";
import { dbClient } from "@/lib/db/client";
export function ItemsList() {
const [items, setItems] = useState([]);
const [loading, setLoading] = useState(true);
useEffect(() => {
async function fetchItems() {
const { data, error } = await dbClient
.from("items")
.select("id, name, status")
.eq("status", "active");
if (error) {
console.error(error);
return;
}
setItems(data || []);
setLoading(false);
}
fetchItems();
}, []);
if (loading) return <div>Loading...</div>;
return (
<ul>
{items.map((item) => (
<li key={item.id}>{item.name}</li>
))}
</ul>
);
}---
Supabase Migration
The Neon JS SDK uses the same PostgREST API as Supabase, making migration straightforward:
Before (Supabase):
import { createClient } from "@supabase/supabase-js";
const client = createClient(SUPABASE_URL, SUPABASE_KEY);After (Neon):
import { createClient, SupabaseAuthAdapter } from "@neondatabase/neon-js";
const client = createClient({
auth: { adapter: SupabaseAuthAdapter(), url: NEON_AUTH_URL },
dataApi: { url: NEON_DATA_API_URL },
});Query syntax remains the same:
// Works identically in both
await client.auth.signInWithPassword({ email, password });
const { data } = await client.from("items").select();Neon Platform API
The Neon Platform API allows you to manage Neon projects, branches, databases, and resources programmatically. You can use the REST API directly or through official SDKs.
Options
| Method | Package/URL | Best For |
|---|---|---|
| REST API | https://console.neon.tech/api/v2/ | Any language, direct HTTP calls |
| TypeScript SDK | @neondatabase/api-client | Node.js, TypeScript projects |
| Python SDK | neon-api | Python scripts and applications |
| CLI | neonctl | Terminal-based management |
Documentation
# REST API documentation
curl -H "Accept: text/markdown" https://neon.tech/docs/reference/api-reference
# TypeScript SDK
curl -H "Accept: text/markdown" https://neon.tech/docs/reference/typescript-sdk
# Python SDK
curl -H "Accept: text/markdown" https://neon.tech/docs/reference/python-sdk
# CLI
curl -H "Accept: text/markdown" https://neon.tech/docs/reference/neon-cliFor the interactive API reference: https://api-docs.neon.tech/reference/getting-started-with-neon-api
Sub-Resources
For detailed information, reference the appropriate sub-resource:
REST API Details
| Topic | Resource |
|---|---|
| Guidelines, Auth, Rate Limits | neon-rest-api/guidelines.md |
| Projects | neon-rest-api/projects.md |
| Branches, Databases, Roles | neon-rest-api/branches.md |
| Compute Endpoints | neon-rest-api/endpoints.md |
| API Keys | neon-rest-api/keys.md |
| Operations | neon-rest-api/operations.md |
| Organizations | neon-rest-api/organizations.md |
SDKs
| Language | Resource |
|---|---|
| TypeScript | neon-typescript-sdk.md |
| Python | neon-python-sdk.md |
Quick Start
Authentication
All API requests require a Neon API key:
Authorization: Bearer $NEON_API_KEYAPI Key Types
| Type | Scope | Best For |
|---|---|---|
| Personal | All projects user has access to | Individual use, scripting |
| Organization | Entire organization | CI/CD, org-wide automation |
| Project-scoped | Single project only | Project-specific integrations |
Rate Limits
- 700 requests per minute (~11 per second)
- Bursts up to 40 requests per second per route
- Handle
429 Too Many Requestswith retry/backoff
Common Operations Quick Reference
| Operation | REST API | TypeScript SDK | Python SDK |
|---|---|---|---|
| List Projects | GET /projects | listProjects({}) | projects() |
| Create Project | POST /projects | createProject({...}) | project_create(...) |
| Get Connection URI | GET /projects/{id}/connection_uri | getConnectionUri({...}) | connection_uri(...) |
| Create Branch | POST /projects/{id}/branches | createProjectBranch(...) | branch_create(...) |
| Start Endpoint | POST /projects/{id}/endpoints/{id}/start | startProjectEndpoint(...) | endpoint_start(...) |
Error Handling
| Status | Meaning | Action |
|---|---|---|
| 401 | Unauthorized | Check API key |
| 404 | Not Found | Verify resource ID |
| 429 | Rate Limited | Implement retry with backoff |
| 500 | Server Error | Retry or contact support |
Neon Python SDK
The neon-api Python SDK is a Pythonic wrapper around the Neon REST API. It provides methods for managing all Neon resources, including projects, branches, endpoints, roles, and databases.
For core concepts (Organization, Project, Branch, Endpoint, etc.), see what-is-neon.md.
Documentation
curl -H "Accept: text/markdown" https://neon.tech/docs/reference/python-sdkInstallation
pip install neon-apiAuthentication
import os
from neon_api import NeonAPI
api_key = os.getenv("NEON_API_KEY")
if not api_key:
raise ValueError("NEON_API_KEY environment variable is not set.")
neon = NeonAPI(api_key=api_key)Projects
List Projects
all_projects = neon.projects()Create Project
new_project = neon.project_create(
project={
'name': 'my-new-project',
'pg_version': 17
}
)Get Project Details
project = neon.project(project_id='your-project-id')Update Project
neon.project_update(
project_id='your-project-id',
project={
'name': 'renamed-project',
'default_endpoint_settings': {
'autoscaling_limit_min_cu': 1,
'autoscaling_limit_max_cu': 2,
}
}
)Delete Project
neon.project_delete(project_id='project-to-delete')Get Connection URI
uri = neon.connection_uri(
project_id='your-project-id',
database_name='neondb',
role_name='neondb_owner'
)
print(f"Connection URI: {uri.uri}")Branches
Create Branch
new_branch = neon.branch_create(
project_id='your-project-id',
branch={'name': 'feature-branch'},
endpoints=[
{'type': 'read_write', 'autoscaling_limit_max_cu': 1}
]
)List Branches
branches = neon.branches(project_id='your-project-id')Get Branch Details
branch = neon.branch(project_id='your-project-id', branch_id='br-xxx')Update Branch
neon.branch_update(
project_id='your-project-id',
branch_id='br-xxx',
branch={'name': 'updated-branch-name'}
)Delete Branch
neon.branch_delete(project_id='your-project-id', branch_id='br-xxx')Databases
Create Database
neon.database_create(
project_id='your-project-id',
branch_id='br-xxx',
database={'name': 'my-app-db', 'owner_name': 'neondb_owner'}
)List Databases
databases = neon.databases(project_id='your-project-id', branch_id='br-xxx')Delete Database
neon.database_delete(
project_id='your-project-id',
branch_id='br-xxx',
database_id='my-app-db'
)Roles
Create Role
new_role = neon.role_create(
project_id='your-project-id',
branch_id='br-xxx',
role_name='app_user'
)
print(f"Password: {new_role.role.password}")List Roles
roles = neon.roles(project_id='your-project-id', branch_id='br-xxx')Delete Role
neon.role_delete(
project_id='your-project-id',
branch_id='br-xxx',
role_name='app_user'
)Endpoints
Create Endpoint
neon.endpoint_create(
project_id='your-project-id',
endpoint={
'branch_id': 'br-xxx',
'type': 'read_only'
}
)Start/Suspend Endpoint
# Start
neon.endpoint_start(project_id='your-project-id', endpoint_id='ep-xxx')
# Suspend
neon.endpoint_suspend(project_id='your-project-id', endpoint_id='ep-xxx')Update Endpoint
neon.endpoint_update(
project_id='your-project-id',
endpoint_id='ep-xxx',
endpoint={'autoscaling_limit_max_cu': 2}
)Delete Endpoint
neon.endpoint_delete(project_id='your-project-id', endpoint_id='ep-xxx')API Keys
List API Keys
api_keys = neon.api_keys()Create API Key
new_key = neon.api_key_create(key_name='my-script-key')
print(f"Key (store securely!): {new_key.key}")Revoke API Key
neon.api_key_revoke(1234) # key IDOperations
List Operations
ops = neon.operations(project_id='your-project-id')Get Operation Details
op = neon.operation(project_id='your-project-id', operation_id='op-xxx')Overview
This document outlines the rules for managing branches in a Neon project using the Neon API.
Manage branches
Create branch
1. Action: Creates a new branch within a specified project. By default, a branch is created from the project's default branch, but you can specify a parent branch, a point-in-time (LSN or timestamp), and attach compute endpoints. 2. Endpoint: POST /projects/{project_id}/branches 3. Path Parameters:
project_id(string, required): The unique identifier of the project where the branch will be created.
4. Body Parameters: The request body is optional. If provided, it can contain endpoints and/or branch objects.
endpoints (array of objects, optional): A list of compute endpoints to create and attach to the new branch.
type(string, required): The endpoint type. Allowed values:read_write,read_only.autoscaling_limit_min_cu(number, optional): The minimum number of Compute Units (CU). Minimum value is0.25.autoscaling_limit_max_cu(number, optional): The maximum number of Compute Units (CU). Minimum value is0.25.provisioner(string, optional): The compute provisioner. Specifyk8s-neonvmto enable Autoscaling. Allowed values:k8s-pod,k8s-neonvm.suspend_timeout_seconds(integer, optional): Duration of inactivity in seconds before a compute is suspended. Ranges from -1 (never suspend) to 604800 (1 week). A value of0uses the default of 300 seconds (5 minutes).
branch (object, optional): Specifies the properties of the new branch.
name(string, optional): A name for the branch (max 256 characters). If omitted, a name is auto-generated.parent_id(string, optional): The ID of the parent branch. If omitted, the project's default branch is used as the parent.parent_lsn(string, optional): A Log Sequence Number (LSN) from the parent branch to create the new branch from a specific point-in-time.parent_timestamp(string, optional): An ISO 8601 timestamp (e.g.,2025-08-26T12:00:00Z) to create the branch from a specific point-in-time.protected(boolean, optional): Iftrue, the branch is created as a protected branch.init_source(string, optional): The source for branch initialization.parent-data(default) copies schema and data.schema-onlycreates a new root branch with only the schema from the specified parent.expires_at(string, optional): An RFC 3339 timestamp for when the branch should be automatically deleted (e.g.,2025-06-09T18:02:16Z).
Example: Create a branch from a specific parent with a read-write compute
curl 'https://console.neon.tech/api/v2/projects/hidden-river-50598307/branches' \
-H 'Accept: application/json' \
-H "Authorization: Bearer $NEON_API_KEY" \
-H 'Content-Type: application/json' \
-d '{
"endpoints": [
{
"type": "read_write"
}
],
"branch": {
"parent_id": "br-super-wildflower-adniii9u",
"name": "my-new-feature-branch"
}
}'Example response
{
"branch": {
"id": "br-damp-glitter-adqd4hk5",
"project_id": "hidden-river-50598307",
"parent_id": "br-super-wildflower-adniii9u",
"parent_lsn": "0/1A7F730",
"name": "my-new-feature-branch",
"current_state": "init",
"pending_state": "ready",
"state_changed_at": "2025-09-10T16:45:52Z",
"creation_source": "console",
"primary": false,
"default": false,
"protected": false,
"cpu_used_sec": 0,
"compute_time_seconds": 0,
"active_time_seconds": 0,
"written_data_bytes": 0,
"data_transfer_bytes": 0,
"created_at": "2025-09-10T16:45:52Z",
"updated_at": "2025-09-10T16:45:52Z",
"created_by": {
"name": "<USER_NAME>",
"image": "<USER_IMAGE_URL>"
},
"init_source": "parent-data"
},
"endpoints": [
{
"host": "ep-raspy-glade-ad8e3gvy.c-2.us-east-1.aws.neon.tech",
"id": "ep-raspy-glade-ad8e3gvy",
"project_id": "hidden-river-50598307",
"branch_id": "br-damp-glitter-adqd4hk5",
"autoscaling_limit_min_cu": 0.25,
"autoscaling_limit_max_cu": 2,
"region_id": "aws-us-east-1",
"type": "read_write",
"current_state": "init",
"pending_state": "active",
"settings": {},
"pooler_enabled": false,
"pooler_mode": "transaction",
"disabled": false,
"passwordless_access": true,
"creation_source": "console",
"created_at": "2025-09-10T16:45:52Z",
"updated_at": "2025-09-10T16:45:52Z",
"proxy_host": "c-2.us-east-1.aws.neon.tech",
"suspend_timeout_seconds": 0,
"provisioner": "k8s-neonvm"
}
],
"operations": [
{
"id": "cf5d0923-fc13-4125-83d5-8fc31c6b0214",
"project_id": "hidden-river-50598307",
"branch_id": "br-damp-glitter-adqd4hk5",
"action": "create_branch",
"status": "running",
"failures_count": 0,
"created_at": "2025-09-10T16:45:52Z",
"updated_at": "2025-09-10T16:45:52Z",
"total_duration_ms": 0
},
{
"id": "e3c60b62-00c8-4ad4-9cd1-cdc3e8fd8154",
"project_id": "hidden-river-50598307",
"branch_id": "br-damp-glitter-adqd4hk5",
"endpoint_id": "ep-raspy-glade-ad8e3gvy",
"action": "start_compute",
"status": "scheduling",
"failures_count": 0,
"created_at": "2025-09-10T16:45:52Z",
"updated_at": "2025-09-10T16:45:52Z",
"total_duration_ms": 0
}
],
"roles": [
{
"branch_id": "br-damp-glitter-adqd4hk5",
"name": "neondb_owner",
"protected": false,
"created_at": "2025-09-10T12:14:58Z",
"updated_at": "2025-09-10T12:14:58Z"
}
],
"databases": [
{
"id": 9554148,
"branch_id": "br-damp-glitter-adqd4hk5",
"name": "neondb",
"owner_name": "neondb_owner",
"created_at": "2025-09-10T12:14:58Z",
"updated_at": "2025-09-10T12:14:58Z"
}
],
"connection_uris": [
{
"connection_uri": "postgresql://neondb_owner:npg_EwcS9IOgFfb7@ep-raspy-glade-ad8e3gvy.c-2.us-east-1.aws.neon.tech/neondb?sslmode=require",
"connection_parameters": {
"database": "neondb",
"password": "npg_EwcS9IOgFfb7",
"role": "neondb_owner",
"host": "ep-raspy-glade-ad8e3gvy.c-2.us-east-1.aws.neon.tech",
"pooler_host": "ep-raspy-glade-ad8e3gvy-pooler.c-2.us-east-1.aws.neon.tech"
}
}
]
}List branches
1. Action: Retrieves a list of branches for the specified project. Supports filtering, sorting, and pagination. 2. Endpoint: GET /projects/{project_id}/branches 3. Path Parameters:
project_id(string, required): The unique identifier of the project.
4. Query Parameters:
search(string, optional): Filters branches by a partial match on name or ID.sort_by(string, optional): The field to sort by. Allowed values:name,created_at,updated_at. Defaults toupdated_at.sort_order(string, optional): The sort order. Allowed values:asc,desc. Defaults todesc.limit(integer, optional): The number of branches to return (1 to 10000).cursor(string, optional): The cursor from a previous response for pagination.
Example: List all branches sorted by creation date
curl 'https://console.neon.tech/api/v2/projects/hidden-river-50598307/branches?sort_by=created_at&sort_order=asc' \
-H 'accept: application/json' \
-H "Authorization: Bearer $NEON_API_KEY"Example response
{
"branches": [
{
"id": "br-long-feather-adpbgzlx",
"project_id": "hidden-river-50598307",
"name": "production",
"current_state": "ready",
"state_changed_at": "2025-09-10T12:15:01Z",
"logical_size": 30785536,
"creation_source": "console",
"primary": true,
"default": true,
"protected": false,
"cpu_used_sec": 82,
"compute_time_seconds": 82,
"active_time_seconds": 316,
"written_data_bytes": 29060360,
"data_transfer_bytes": 0,
"created_at": "2025-09-10T12:14:58Z",
"updated_at": "2025-09-10T12:35:33Z",
"created_by": {
"name": "<USER_NAME>",
"image": "<USER_IMAGE_URL>"
},
"init_source": "parent-data"
},
{
"id": "br-super-wildflower-adniii9u",
"project_id": "hidden-river-50598307",
"parent_id": "br-long-feather-adpbgzlx",
"parent_lsn": "0/1A33BC8",
"parent_timestamp": "2025-09-10T12:15:03Z",
"name": "development",
"current_state": "ready",
"state_changed_at": "2025-09-10T12:15:04Z",
"logical_size": 30842880,
"creation_source": "console",
"primary": false,
"default": false,
"protected": false,
"cpu_used_sec": 78,
"compute_time_seconds": 78,
"active_time_seconds": 312,
"written_data_bytes": 310120,
"data_transfer_bytes": 0,
"created_at": "2025-09-10T12:15:04Z",
"updated_at": "2025-09-10T12:35:33Z",
"created_by": {
"name": "<USER_NAME>",
"image": "<USER_IMAGE_URL>"
},
"init_source": "parent-data"
}
],
"annotations": {
"br-long-feather-adpbgzlx": {
"object": {
"type": "console/branch",
"id": "br-long-feather-adpbgzlx"
},
"value": {
"environment": "production"
},
"created_at": "2025-09-10T12:14:58Z",
"updated_at": "2025-09-10T12:14:58Z"
}
},
"pagination": {
"sort_by": "created_at",
"sort_order": "ASC"
}
}Retrieve branch details
1. Action: Retrieves detailed information about a specific branch, including its parent, creation timestamp, and state. 2. Endpoint: GET /projects/{project_id}/branches/{branch_id} 3. Path Parameters:
project_id(string, required): The unique identifier of the project.branch_id(string, required): The unique identifier of the branch.
Example Request:
curl 'https://console.neon.tech/api/v2/projects/hidden-river-50598307/branches/br-super-wildflower-adniii9u' \
-H 'accept: application/json' \
-H "Authorization: Bearer $NEON_API_KEY"Example Response:
{
"branch": {
"id": "br-super-wildflower-adniii9u",
"project_id": "hidden-river-50598307",
"parent_id": "br-long-feather-adpbgzlx",
"parent_lsn": "0/1A33BC8",
"parent_timestamp": "2025-09-10T12:15:03Z",
"name": "development",
"current_state": "ready",
"state_changed_at": "2025-09-10T12:15:04Z",
"logical_size": 30842880,
"creation_source": "console",
"primary": false,
"default": false,
"protected": false,
"cpu_used_sec": 78,
"compute_time_seconds": 78,
"active_time_seconds": 312,
"written_data_bytes": 310120,
"data_transfer_bytes": 0,
"created_at": "2025-09-10T12:15:04Z",
"updated_at": "2025-09-10T12:35:33Z",
"created_by": {
"name": "<USER_NAME>",
"image": "<USER_IMAGE_URL>"
},
"init_source": "parent-data"
},
"annotation": {
"object": {
"type": "console/branch",
"id": "br-super-wildflower-adniii9u"
},
"value": {
"environment": "development"
},
"created_at": "2025-09-10T12:15:04Z",
"updated_at": "2025-09-10T12:15:04Z"
}
}Update branch
1. Action: Updates the properties of a specified branch, such as its name, protection status, or expiration time. 2. Endpoint: PATCH /projects/{project_id}/branches/{branch_id} 3. Path Parameters:
project_id(string, required): The unique identifier of the project.branch_id(string, required): The unique identifier of the branch to update.
4. Body Parameters: branch (object, required): The container for the branch attributes to update.
name(string, optional): A new name for the branch (max 256 characters).protected(boolean, optional): Set totrueto protect the branch orfalseto unprotect it.expires_at(string or null, optional): Set a new RFC 3339 expiration timestamp ornullto remove the expiration.
Example: Change branch name:
curl -X 'PATCH' \
'https://console.neon.tech/api/v2/projects/hidden-river-50598307/branches/br-damp-glitter-adqd4hk5' \
-H 'accept: application/json' \
-H "Authorization: Bearer $NEON_API_KEY" \
-H 'Content-Type: application/json' \
-d '{
"branch": {
"name": "updated-branch-name"
}
}'Example response:
{
"branch": {
"id": "br-damp-glitter-adqd4hk5",
"project_id": "hidden-river-50598307",
"parent_id": "br-super-wildflower-adniii9u",
"parent_lsn": "0/1A7F730",
"parent_timestamp": "2025-09-10T12:15:05Z",
"name": "updated-branch-name",
"current_state": "ready",
"state_changed_at": "2025-09-10T16:45:52Z",
"logical_size": 30842880,
"creation_source": "console",
"primary": false,
"default": false,
"protected": false,
"cpu_used_sec": 68,
"compute_time_seconds": 68,
"active_time_seconds": 268,
"written_data_bytes": 0,
"data_transfer_bytes": 0,
"created_at": "2025-09-10T16:45:52Z",
"updated_at": "2025-09-10T16:55:30Z",
"created_by": {
"name": "<USER_NAME>",
"image": "<USER_IMAGE_URL>"
},
"init_source": "parent-data"
},
"operations": []
}Delete branch
1. Action: Deletes the specified branch from a project. This action will also place all associated compute endpoints into an idle state, breaking any active client connections. 2. Endpoint: DELETE /projects/{project_id}/branches/{branch_id} 3. Path Parameters:
project_id(string, required): The unique identifier of the project.branch_id(string, required): The unique identifier of the branch to delete.
4. Constraints:
- You cannot delete a project's root or default branch.
- You cannot delete a branch that has child branches. You must delete all child branches first.
Example Request:
curl -X 'DELETE' \
'https://console.neon.tech/api/v2/projects/{project_id}/branches/{branch_id}' \
-H 'accept: application/json' \
-H "Authorization: Bearer $NEON_API_KEY"List branch endpoints
1. Action: Retrieves a list of all compute endpoints that are associated with a specific branch. 2. Endpoint: GET /projects/{project_id}/branches/{branch_id}/endpoints 3. Path Parameters:
project_id(string, required): The unique identifier of the project.branch_id(string, required): The unique identifier of the branch whose endpoints you want to list.
4. A branch can have one read_write compute endpoint and multiple read_only endpoints. This method returns an array of all endpoints currently attached to the specified branch.
Example Request:
curl 'https://console.neon.tech/api/v2/projects/hidden-river-50598307/branches/br-super-wildflower-adniii9u/endpoints' \
-H 'accept: application/json' \
-H "Authorization: Bearer $NEON_API_KEY"Manage databases
Create database
1. Action: Creates a new database within a specified branch. A branch can contain multiple databases. 2. Endpoint: POST /projects/{project_id}/branches/{branch_id}/databases 3. Path Parameters:
project_id(string, required): The unique identifier of the project.branch_id(string, required): The unique identifier of the branch where the database will be created.
4. Body Parameters: database (object, required): The container for the new database's properties.
name(string, required): The name for the new database.owner_name(string, required): The name of an existing role that will own the database.
Example Request:
curl 'https://console.neon.tech/api/v2/projects/hidden-river-50598307/branches/br-super-wildflower-adniii9u/databases' \
-H 'Accept: application/json' \
-H "Authorization: Bearer $NEON_API_KEY" \
-H 'Content-Type: application/json' \
-d '{
"database": {
"name": "my_new_app_db",
"owner_name": "app_owner_role"
}
}'List databases
1. Action: Retrieves a list of all databases within a specified branch. 2. Endpoint: GET /projects/{project_id}/branches/{branch_id}/databases 3. Path Parameters:
project_id(string, required): The unique identifier of the project.branch_id(string, required): The unique identifier of the branch.
Example Request:
curl 'https://console.neon.tech/api/v2/projects/hidden-river-50598307/branches/br-super-wildflower-adniii9u/databases' \
-H 'Accept: application/json' \
-H "Authorization: Bearer $NEON_API_KEY"Retrieve database details
1. Action: Retrieves detailed information about a specific database within a branch. 2. Endpoint: GET /projects/{project_id}/branches/{branch_id}/databases/{database_name} 3. Path Parameters:
project_id(string, required): The unique identifier of the project.branch_id(string, required): The unique identifier of the branch.database_name(string, required): The name of the database.
Update database
1. Action: Updates the properties of a specified database, such as its name or owner. 2. Endpoint: PATCH /projects/{project_id}/branches/{branch_id}/databases/{database_name} 3. Path Parameters:
project_id(string, required): The unique identifier of the project.branch_id(string, required): The unique identifier of the branch.database_name(string, required): The current name of the database to update.
4. Body Parameters: database (object, required): The container for the database attributes to update.
name(string, optional): A new name for the database.owner_name(string, optional): The name of a different existing role to become the new owner.
Delete database
1. Action: Deletes the specified database from a branch. This action is permanent and cannot be undone. 2. Endpoint: DELETE /projects/{project_id}/branches/{branch_id}/databases/{database_name} 3. Path Parameters:
project_id(string, required): The unique identifier of the project.branch_id(string, required): The unique identifier of the branch.database_name(string, required): The name of the database to delete.
Manage roles
Create role
1. Action: Creates a new Postgres role in a specified branch. This action may drop existing connections to the active compute endpoint. 2. Endpoint: POST /projects/{project_id}/branches/{branch_id}/roles 3. Path Parameters:
project_id(string, required): The unique identifier of the project.branch_id(string, required): The unique identifier of the branch where the role will be created.
4. Body Parameters: role (object, required): The container for the new role's properties.
name(string, required): The name for the new role. Cannot exceed 63 bytes in length.no_login(boolean, optional): Iftrue, creates a role that cannot be used to log in. Defaults tofalse.
Example Request:
curl 'https://console.neon.tech/api/v2/projects/hidden-river-50598307/branches/br-super-wildflower-adniii9u/roles' \
-H 'Accept: application/json' \
-H "Authorization: Bearer $NEON_API_KEY" \
-H 'Content-Type: application/json' \
-d '{
"role": {
"name": "new_app_user"
}
}'List roles
1. Action: Retrieves a list of all Postgres roles from the specified branch. 2. Endpoint: GET /projects/{project_id}/branches/{branch_id}/roles 3. Path Parameters:
project_id(string, required): The unique identifier of the project.branch_id(string, required): The unique identifier of the branch.
Retrieve role details
1. Action: Retrieves detailed information about a specific Postgres role within a branch. 2. Endpoint: GET /projects/{project_id}/branches/{branch_id}/roles/{role_name} 3. Path Parameters:
project_id(string, required): The unique identifier of the project.branch_id(string, required): The unique identifier of the branch.role_name(string, required): The name of the role.
Delete role
1. Action: Deletes the specified Postgres role from the branch. This action is permanent. 2. Endpoint: DELETE /projects/{project_id}/branches/{branch_id}/roles/{role_name} 3. Path Parameters:
project_id(string, required): The unique identifier of the project.branch_id(string, required): The unique identifier of the branch.role_name(string, required): The name of the role to delete.
Overview
This section provides rules for managing compute endpoints associated with branches in a project. Compute endpoints are Neon compute instances that allow you to connect to and interact with your databases.
Manage compute endpoints
Create compute endpoint
1. Action: Creates a new compute endpoint (a Neon compute instance) and associates it with a specified branch. 2. Endpoint: POST /projects/{project_id}/endpoints 3. Path Parameters:
project_id(string, required): The unique identifier of the project.
4. Body Parameters: endpoint (object, required): The container for the new endpoint's properties.
branch_id(string, required): The ID of the branch to associate the endpoint with.type(string, required): The endpoint type. A branch can have only oneread_writeendpoint but multipleread_onlyendpoints. Allowed values:read_write,read_only.region_id(string, optional): The region where the endpoint will be created. Must match the project's region.autoscaling_limit_min_cu(number, optional): The minimum number of Compute Units (CU). Minimum0.25.autoscaling_limit_max_cu(number, optional): The maximum number of Compute Units (CU). Minimum0.25.provisioner(string, optional): The compute provisioner. Specifyk8s-neonvmto enable Autoscaling. Allowed values:k8s-pod,k8s-neonvm.suspend_timeout_seconds(integer, optional): Duration of inactivity in seconds before suspending the compute. Ranges from -1 (never suspend) to 604800 (1 week).disabled(boolean, optional): Iftrue, restricts connections to the endpoint.
Example Request:
curl 'https://console.neon.tech/api/v2/projects/hidden-river-50598307/endpoints' \
-H 'Accept: application/json' \
-H "Authorization: Bearer $NEON_API_KEY" \
-H 'Content-Type: application/json' \
-d '{
"endpoint": {
"branch_id": "br-your-branch-id",
"type": "read_only"
}
}'Example Response:
{
"endpoint": {
"host": "ep-proud-mud-adwmnxz4.c-2.us-east-1.aws.neon.tech",
"id": "ep-proud-mud-adwmnxz4",
"project_id": "hidden-river-50598307",
"branch_id": "br-super-wildflower-adniii9u",
"autoscaling_limit_min_cu": 0.25,
"autoscaling_limit_max_cu": 2,
"region_id": "aws-us-east-1",
"type": "read_only",
"current_state": "init",
"pending_state": "active",
"settings": {},
"pooler_enabled": false,
"pooler_mode": "transaction",
"disabled": false,
"passwordless_access": true,
"creation_source": "console",
"created_at": "2025-09-11T06:25:12Z",
"updated_at": "2025-09-11T06:25:12Z",
"proxy_host": "c-2.us-east-1.aws.neon.tech",
"suspend_timeout_seconds": 0,
"provisioner": "k8s-neonvm"
},
"operations": [
{
"id": "4d10642f-5212-4517-ad60-afd28c9096e2",
"project_id": "hidden-river-50598307",
"branch_id": "br-super-wildflower-adniii9u",
"endpoint_id": "ep-proud-mud-adwmnxz4",
"action": "start_compute",
"status": "running",
"failures_count": 0,
"created_at": "2025-09-11T06:25:12Z",
"updated_at": "2025-09-11T06:25:12Z",
"total_duration_ms": 0
}
]
}List compute endpoints
1. Action: Retrieves a list of all compute endpoints for the specified project. 2. Endpoint: GET /projects/{project_id}/endpoints 3. Path Parameters:
project_id(string, required): The unique identifier of the project.
Example Request:
curl 'https://console.neon.tech/api/v2/projects/hidden-river-50598307/endpoints' \
-H 'Accept: application/json' \
-H "Authorization: Bearer $NEON_API_KEY"Retrieve compute endpoint details
1. Action: Retrieves detailed information about a specific compute endpoint, including its configuration (e.g., autoscaling limits), current state (active or idle), and associated branch ID. 2. Endpoint: GET /projects/{project_id}/endpoints/{endpoint_id} 3. Path Parameters:
project_id(string, required): The unique identifier of the project.endpoint_id(string, required): The unique identifier of the compute endpoint).
Example Request:
curl 'https://console.neon.tech/api/v2/projects/hidden-river-50598307/endpoints/ep-proud-mud-adwmnxz4' \
-H 'Accept: application/json' \
-H "Authorization: Bearer $NEON_API_KEY"Update compute endpoint
1. Action: Updates the configuration of a specified compute endpoint. 2. Endpoint: PATCH /projects/{project_id}/endpoints/{endpoint_id} 3. Path Parameters:
project_id(string, required): The unique identifier of the project.endpoint_id(string, required): The unique identifier of the compute endpoint.
4. Body Parameters: endpoint (object, required): The container for the endpoint attributes to update.
autoscaling_limit_min_cu(number, optional): A new minimum number of Compute Units (CU).autoscaling_limit_max_cu(number, optional): A new maximum number of Compute Units (CU).suspend_timeout_seconds(integer, optional): A new inactivity period in seconds before suspension.disabled(boolean, optional): Set totrueto disable connections orfalseto enable them.provisioner(string, optional): Change the compute provisioner.
Example: Update autoscaling limits
curl -X 'PATCH' \
'https://console.neon.tech/api/v2/projects/hidden-river-50598307/endpoints/ep-proud-mud-adwmnxz4' \
-H 'Accept: application/json' \
-H "Authorization: Bearer $NEON_API_KEY" \
-H 'Content-Type: application/json' \
-d '{
"endpoint": {
"autoscaling_limit_min_cu": 0.5,
"autoscaling_limit_max_cu": 1
}
}'Delete compute endpoint
1. Action: Deletes the specified compute endpoint. This action drops any existing network connections to the endpoint. 2. Endpoint: DELETE /projects/{project_id}/endpoints/{endpoint_id} 3. Path Parameters:
project_id(string, required): The unique identifier of the project.endpoint_id(string, required): The unique identifier of the compute endpoint to delete.
Example Request:
curl -X 'DELETE' \
'https://console.neon.tech/api/v2/projects/hidden-river-50598307/endpoints/ep-proud-mud-adwmnxz4' \
-H 'Accept: application/json' \
-H "Authorization: Bearer $NEON_API_KEY"Start compute endpoint
1. Action: Manually starts a compute endpoint that is currently in an idle state. The endpoint is ready for connections once the start operation completes successfully. 2. Endpoint: POST /projects/{project_id}/endpoints/{endpoint_id}/start 3. Path Parameters:
project_id(string, required): The unique identifier of the project.endpoint_id(string, required): The unique identifier of the compute endpoint.
Example Request:
curl -X 'POST' \
'https://console.neon.tech/api/v2/projects/hidden-river-50598307/endpoints/ep-ancient-brook-ad5ea04d/start' \
-H 'Accept: application/json' \
-H "Authorization: Bearer $NEON_API_KEY"Suspend compute endpoint
1. Action: Manually suspends an active compute endpoint, forcing it into an idle state. This will immediately drop any active connections to the endpoint. 2. Endpoint: POST /projects/{project_id}/endpoints/{endpoint_id}/suspend 3. Path Parameters:
project_id(string, required): The unique identifier of the project.endpoint_id(string, required): The unique identifier of the compute endpoint.
Example Request:
curl -X 'POST' \
'https://console.neon.tech/api/v2/projects/hidden-river-50598307/endpoints/ep-ancient-brook-ad5ea04d/suspend' \
-H 'Accept: application/json' \
-H "Authorization: Bearer $NEON_API_KEY"Restart compute endpoint
1. Action: Restarts the specified compute endpoint. This involves an immediate suspend operation followed by a start operation. This is useful for applying configuration changes or refreshing the compute instance. All active connections will be dropped. 2. Endpoint: POST /projects/{project_id}/endpoints/{endpoint_id}/restart 3. Path Parameters:
project_id(string, required): The unique identifier of the project.endpoint_id(string, required): The unique identifier of the compute endpoint.
Example Request:
curl -X 'POST' \
'https://console.neon.tech/api/v2/projects/hidden-river-50598307/endpoints/ep-ancient-brook-ad5ea04d/restart' \
-H 'Accept: application/json' \
-H "Authorization: Bearer $NEON_API_KEY"Overview
This document provides a comprehensive set of rules and guidelines for an AI agent to interact with the Neon API. The Neon API is a RESTful service that allows for programmatic management of all Neon resources. Adherence to these rules ensures correct, efficient, and safe API usage.
General API guidelines
All Neon API requests must be made to the following base URL:
https://console.neon.tech/api/v2/To construct a full request URL, append the specific endpoint path to this base URL.
Authentication
- All API requests must be authenticated using a Neon API key.
- The API key must be included in the
Authorizationheader using theBearerauthentication scheme. - The header should be formatted as:
Authorization: Bearer $NEON_API_KEY, where$NEON_API_KEYis a valid Neon API key. - A request without a valid
Authorizationheader will fail with a401 Unauthorizedstatus code.
API rate limiting
- Neon limits API requests to 700 requests per minute (approximately 11 per second).
- Bursts of up to 40 requests per second per route are permitted.
- If the rate limit is exceeded, the API will respond with an
HTTP 429 Too Many Requestserror. - Your application logic must handle
429errors and implement a retry strategy with appropriate backoff.
Neon Core Concepts
To effectively use the Neon Python SDK, it's essential to understand the hierarchy and purpose of its core resources. The following table provides a high-level overview of each concept.
| Concept | Description | Analogy/Purpose | Key Relationship |
|---|---|---|---|
| Organization | The highest-level container, managing billing, users, and multiple projects. | A GitHub Organization or a company's cloud account. | Contains one or more Projects. |
| Project | The primary container that contains all related database resources for a single application or service. | A Git repository or a top-level folder for an application. | Lives within an Organization (or a personal account). Contains Branches. |
| Branch | A lightweight, copy-on-write clone of a database's state at a specific point in time. | A git branch. Used for isolated development, testing, staging, or previews without duplicating storage costs. | Belongs to a Project. Contains its own set of Databases and Roles, cloned from its parent. |
| Compute Endpoint | The actual running PostgreSQL instance that you connect to. It provides the CPU and RAM for processing queries. | The "server" or "engine" for your database. It can be started, suspended (scaled to zero), and resized. | Is attached to a single Branch. Your connection string points to a Compute Endpoint's hostname. |
| Database | A logical container for your data (tables, schemas, views) within a branch. It follows standard PostgreSQL conventions. | A single database within a PostgreSQL server instance. | Exists within a Branch. A branch can have multiple databases. |
| Role | A PostgreSQL role used for authentication (logging in) and authorization (permissions to access data). | A database user account with a username and password. | Belongs to a Branch. Roles from a parent branch are copied to child branches upon creation. |
| API Key | A secret token used to authenticate requests to the Neon API. Keys have different scopes (Personal, Organization, Project-scoped). | A password for programmatic access, allowing you to manage all other Neon resources. | Authenticates actions on Organizations, Projects, Branches, etc. |
| Operation | An asynchronous action performed by the Neon control plane, such as creating a branch or starting a compute. | A background job or task. Its status can be polled to know when an action is complete. | Associated with a Project and often a specific Branch or Endpoint. Essential for scripting API calls. |
Understanding API key types
When performing actions via the API, you must select the correct type of API key based on the required scope and permissions. There are three types:
1. Personal API Key
- Scope: Accesses all projects that the user who created the key is a member of.
- Permissions: The key has the same permissions as its owner. If the user's access is revoked from an organization, the key loses access too.
- Best For: Individual use, scripting, and tasks tied to a specific user's permissions.
- Created By: Any user.
2. Organization API Key
- Scope: Accesses all projects and resources within an entire organization.
- Permissions: Has admin-level access across the organization, independent of any single user. It remains valid even if the creator leaves the organization.
- Best For: CI/CD pipelines, organization-wide automation, and service accounts that need broad access.
- Created By: Organization administrators only.
3. Project-scoped API Key
- Scope: Access is strictly limited to a single, specified project.
- Permissions: Cannot perform organization-level actions (like creating new projects) or delete the project it is scoped to. This is the most secure and limited key type.
- Best For: Project-specific integrations, third-party services, or automation that should be isolated to one project.
- Created By: Any organization member.
Overview
This document outlines the rules for managing Neon API keys programmatically. It covers listing existing keys, creating new keys, and revoking keys.
Important note on creating API keys
To create new API keys using the API, you must already possess a valid Personal API Key. The first key must be created from the Neon Console. You can ask the user to create one for you if you do not have one.
List API keys
- Endpoint:
GET /api_keys - Authorization: Use a Personal API Key.
Example request:
curl "https://console.neon.tech/api/v2/api_keys" \
-H "Authorization: Bearer $PERSONAL_API_KEY"Example response:
[
{
"id": 2291506,
"name": "my-personal-key",
"created_at": "2025-09-10T09:44:04Z",
"created_by": {
"id": "487de658-08ba-4363-b387-86d18b9ad1c8",
"name": "<USER_NAME>",
"image": "<USER_IMAGE_URL>"
},
"last_used_at": "2025-09-10T09:44:09Z",
"last_used_from_addr": "49.43.218.132,34.211.200.85"
}
]Create an API key
- Endpoint:
POST /api_keys - Authorization: Use a Personal API Key.
- Body: Must include a
key_name.
Example request:
curl https://console.neon.tech/api/v2/api_keys \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $PERSONAL_API_KEY" \
-d '{"key_name": "my-new-key"}'Example response:
{
"id": 2291515,
"key": "napi_9tlr13774gizljemrr133j5koy3bmsphj8iu38mh0yjl9q4r1b0jy2wuhhuxouzr",
"name": "my-new-key",
"created_at": "2025-09-10T09:47:59Z",
"created_by": "487de658-08ba-4363-b387-86d18b9ad1c8"
}Revoke an API key
- Endpoint:
DELETE /api_keys/{key_id} - Authorization: Use a Personal API Key.
Example request:
curl -X DELETE \
'https://console.neon.tech/api/v2/api_keys/2291515' \
-H "Authorization: Bearer $PERSONAL_API_KEY"Example response:
{
"id": 2291515,
"name": "mynewkey",
"created_at": "2025-09-10T09:47:59Z",
"created_by": "487de658-08ba-4363-b387-86d18b9ad1c8",
"last_used_at": "2025-09-10T09:53:01Z",
"last_used_from_addr": "2405:201:c01f:7013:d962:2b4f:2740:9750",
"revoked": true
}