Database

Passthrough

Serverless PostgreSQL with instant branching, autoscaling, and point-in-time recovery.

Instant Branching

Database copies in seconds

Autoscaling

0.25 to 4 compute units

Point-in-Time Recovery

Restore to any second

Global Distribution

Read replicas worldwide

Overview

The Database service provides fully managed serverless PostgreSQL. Features automatic scaling from 0.25 to 4 compute units, instant database branching for development, and point-in-time recovery. Perfect for modern applications that need reliability without operational overhead.

Setup

After creating your app in the dashboard, you'll receive a connection string:

.env.local
# Pooled connection (use for most queries)
DATABASE_URL="postgresql://user:pass@host/db?sslmode=require"

# Direct connection (use for migrations)
DATABASE_URL_UNPOOLED="postgresql://user:pass@host/db?sslmode=require"
PropertyTypeDescription
DATABASE_URLstringPrimary connection string (pooled)
DATABASE_URL_UNPOOLEDstringDirect connection for migrations

Using with Drizzle ORM

Recommended setup with Drizzle ORM:

src/lib/db/index.ts
import { drizzle } from 'drizzle-orm/neon-http'
import { neon } from '@neondatabase/serverless'
import * as schema from './schema'

const sql = neon(process.env.DATABASE_URL!)

export const db = drizzle(sql, { schema })
src/lib/db/schema.ts
import { pgTable, text, timestamp, uuid } from 'drizzle-orm/pg-core'

export const users = pgTable('users', {
  id: uuid('id').primaryKey().defaultRandom(),
  email: text('email').notNull().unique(),
  name: text('name'),
  createdAt: timestamp('created_at').defaultNow().notNull(),
})

Queries

Query your database with type-safe methods:

import { db } from '@/lib/db'
import { users } from '@/lib/db/schema'
import { eq } from 'drizzle-orm'

// Select all users
const allUsers = await db.select().from(users)

// Find by email
const user = await db.select()
  .from(users)
  .where(eq(users.email, 'user@example.com'))
  .limit(1)

// Insert a new user
const newUser = await db.insert(users).values({
  email: 'user@example.com',
  name: 'John Doe',
}).returning()

console.log('Created:', newUser[0].id)

Migrations

Run migrations using the unpooled connection:

drizzle.config.ts
import { defineConfig } from 'drizzle-kit'

export default defineConfig({
  schema: './src/lib/db/schema.ts',
  out: './drizzle',
  dialect: 'postgresql',
  dbCredentials: {
    // Use unpooled connection for migrations
    url: process.env.DATABASE_URL_UNPOOLED!,
  },
})
Terminal
# Generate migration
npx drizzle-kit generate

# Apply migration
npx drizzle-kit migrate

# Open Drizzle Studio
npx drizzle-kit studio

Connection Pooling

Use the pooled connection (DATABASE_URL) for queries and the unpooled connection (DATABASE_URL_UNPOOLED) for migrations and schema changes.

Database Branching

Create instant database branches for development and testing:

import { platform } from '@/lib/platform'

// Create a branch from production
const branch = await platform.database.createBranch({
  name: 'feature-user-profiles',
  parentBranch: 'main',
})

console.log(branch.connectionString)
// Use this connection string for your feature branch

// Delete branch when done
await platform.database.deleteBranch('feature-user-profiles')

CI/CD Integration

Create a branch for each pull request to test migrations safely. Delete the branch when the PR is merged.

Connection Pooling

Built-in PgBouncer connection pooling for serverless environments:

// Connection pool is managed automatically
// Each serverless function gets a pooled connection

// For connection-sensitive operations, use unpooled:
import { neon } from '@neondatabase/serverless'

const directSql = neon(process.env.DATABASE_URL_UNPOOLED!)

// Run a transaction
const result = await directSql`
  BEGIN;
  INSERT INTO users (email) VALUES ('new@example.com');
  COMMIT;
`

Point-in-Time Recovery

Restore your database to any point in the last 7 days:

import { platform } from '@/lib/platform'

// Restore to a specific timestamp
await platform.database.restore({
  branch: 'main',
  timestamp: '2024-01-15T10:30:00Z',
})

// Or restore to a specific LSN (Log Sequence Number)
await platform.database.restore({
  branch: 'main',
  lsn: '0/1234567',
})