Database Providers

Connecting Nebutra to Neon, Supabase, or PlanetScale Postgres — environment variables, connection pooling, and migration setup for each provider.

Nebutra supports three managed PostgreSQL providers out of the box: Neon, Supabase, and PlanetScale Postgres. The application code is identical across these providers. The differences are connection strings, pooler behavior, and how you enable provider-managed PostgreSQL extensions.

All supported providers on this page are PostgreSQL. Keep provider = "postgresql" in Prisma, commit generated migrations, and run migrations through DIRECT_URL.

PlanetScale Vitess/MySQL is not the same support path as PlanetScale Postgres. It requires a separate schema, adapter, relation, index, and migration strategy, so it is treated as a future/template path rather than a supported core runtime.

Neon is the default provider. It is a serverless PostgreSQL platform with branching, auto-suspend, and a generous free tier. PgBouncer connection pooling is built in.

Why Neon

  • Branching — create an isolated database branch for each feature branch or PR, with zero data-copy cost
  • Serverless — scales to zero when idle; no compute charge for dormant databases
  • Auto-suspend — free tier databases pause after 5 minutes of inactivity and resume in ~500 ms
  • pgvector — enabled by default on all Neon databases

Connection string format

Neon provides two URLs per database: a pooled URL (via PgBouncer) for runtime queries, and a direct URL for migrations.

# Pooled — use this for all application queries
postgresql://USER:[email protected]/neondb?sslmode=require&pgbouncer=true

# Direct — use this for migrations only
postgresql://USER:[email protected]/neondb?sslmode=require

Environment variables

# Runtime queries (pooled via PgBouncer)
DATABASE_URL="postgresql://USER:[email protected]/neondb?sslmode=require&pgbouncer=true"

# Migrations only (direct connection — bypasses pooler)
DIRECT_URL="postgresql://USER:[email protected]/neondb?sslmode=require"

Prisma datasource and migration config

datasource db {
  provider = "postgresql"
}
const runtimeDatabaseUrl = process.env.DATABASE_URL ?? "";
const migrationDatabaseUrl = process.env.DIRECT_URL ?? process.env.DATABASE_URL;

Connection pooling with PgBouncer

Neon's PgBouncer operates in transaction mode — a connection is held only for the duration of a single transaction, then returned to the pool. This supports thousands of concurrent application connections with a small number of actual PostgreSQL connections.

PgBouncer transaction mode does not support SET statements that persist across transactions (e.g. SET LOCAL for RLS). Nebutra's withRls sets the tenant variable inside a transaction, which is compatible with transaction-mode pooling.

Database branching for development

Create a branch from the Neon console or CLI to get an isolated copy of your schema for a feature branch:

# Neon CLI
neon branches create --name feature/new-model --parent main

Each branch has its own DATABASE_URL. Set it in your local .env or in Vercel's environment variable settings per branch.

Supabase is a PostgreSQL platform with a managed dashboard, built-in auth, storage, and real-time subscriptions. Connection pooling is provided by Supavisor.

Why Supabase

  • Managed dashboard — browse tables, run SQL, and view RLS policies in the Supabase Studio UI
  • Supavisor — session-mode pooling that supports SET LOCAL statements needed for RLS
  • pgvector — available as a first-class extension, enableable from the dashboard
  • Storage — S3-compatible object storage co-located with your database (used by @nebutra/uploads)

Enabling pgvector

Before running migrations, enable the pgvector extension from the Supabase dashboard:

Dashboard → Database → Extensions → Search "vector" → Enable

Or via SQL in the Supabase SQL editor:

CREATE EXTENSION IF NOT EXISTS vector;

Connection string format

Supabase provides a pooled URL (Supavisor) and a direct URL per project:

# Pooled via Supavisor (session mode — supports SET LOCAL)
postgresql://postgres.PROJECTREF:[email protected]:5432/postgres

# Direct connection (for migrations)
postgresql://postgres:[email protected]:5432/postgres

Environment variables

# Runtime queries (pooled via Supavisor)
DATABASE_URL="postgresql://postgres.PROJECTREF:[email protected]:5432/postgres"

# Migrations only (direct connection)
DIRECT_URL="postgresql://postgres:[email protected]:5432/postgres"

Prisma datasource and migration config

datasource db {
  provider = "postgresql"
}
const runtimeDatabaseUrl = process.env.DATABASE_URL ?? "";
const migrationDatabaseUrl = process.env.DIRECT_URL ?? process.env.DATABASE_URL;

Connection pooling with Supavisor

Supabase's Supavisor supports both transaction mode (port 6543) and session mode (port 5432). Use session mode (port 5432 in the pooled URL above) to ensure SET LOCAL statements for RLS work correctly.

If you use Supavisor in transaction mode (port 6543), SET LOCAL for RLS will not persist across statements in the same logical request. Always use session mode (port 5432) with Supabase when relying on withRls.

Running migrations with Supabase

Migrations work exactly the same as with Neon:

pnpm db:migrate

Prisma uses DIRECT_URL for DDL statements and DATABASE_URL for all other queries.

PlanetScale Postgres is the supported PlanetScale path for Nebutra. It keeps the same Prisma PostgreSQL datasource and uses PlanetScale's Postgres PgBouncer endpoint for runtime traffic.

Why PlanetScale Postgres

  • PostgreSQL-compatible runtime — keeps Sailor's Prisma, RLS, and pgvector assumptions intact
  • PgBouncer endpoint — use port 6432 for pooled application traffic
  • Direct endpoint — use port 5432 for Prisma migrations, introspection, backups, and other DDL-heavy work
  • Branching and operations — use PlanetScale's managed branching, backups, metrics, and operational tooling without changing application code

Enable pgvector

Nebutra's AI features require the pgvector extension. Before the first migration, enable it with an administrative PlanetScale Postgres role:

CREATE EXTENSION IF NOT EXISTS vector;

Connection string format

PlanetScale Postgres provides the same host, credentials, and database name for both connection modes. The port selects the mode, and SSL is required.

# Pooled via PgBouncer — use this for application queries
postgresql://ROLE.BRANCH_ID:PASSWORD@HOSTNAME:6432/DATABASE?sslmode=require

# Direct Postgres — use this for migrations and DDL
postgresql://ROLE.BRANCH_ID:PASSWORD@HOSTNAME:5432/DATABASE?sslmode=require

Environment variables

# Runtime queries (pooled via PgBouncer)
DATABASE_URL="postgresql://ROLE.BRANCH_ID:PASSWORD@HOSTNAME:6432/DATABASE?sslmode=require"

# Migrations only (direct connection — bypasses PgBouncer)
DIRECT_URL="postgresql://ROLE.BRANCH_ID:PASSWORD@HOSTNAME:5432/DATABASE?sslmode=require"

Prisma datasource and migration config

datasource db {
  provider = "postgresql"
}
const runtimeDatabaseUrl = process.env.DATABASE_URL ?? "";
const migrationDatabaseUrl = process.env.DIRECT_URL ?? process.env.DATABASE_URL;

Connection pooling with PgBouncer

PlanetScale Postgres PgBouncer runs in transaction mode. Use it for normal OLTP application queries. Do not use the pooled URL for schema changes, long-running analytics, backups, or session-specific features that require a persistent connection.

Keep RLS tenant context transaction-scoped. Nebutra's withRls helper sets tenant variables inside the transaction; new code should not rely on session variables that survive across pooled transactions.

Keep Prisma migrations on the direct URL. Do not switch Nebutra's Postgres migration workflow to db push for PlanetScale Postgres; checked-in migrations remain the source of truth.

Running migrations with PlanetScale Postgres

Migrations work the same way as other PostgreSQL providers:

pnpm db:migrate

Prisma uses DIRECT_URL for DDL statements and DATABASE_URL for runtime queries.

Choosing a provider

CriteriaNeonSupabasePlanetScale Postgres
BranchingYes — per-branch databasesNoYes — managed database branches
Managed dashboardBasicFull-featured Studio UIOperational dashboard with metrics and branches
Connection poolingPgBouncer (transaction mode)Supavisor (session + transaction modes)PgBouncer (transaction mode, port 6432)
Direct migration URLDirect Postgres URLDirect Postgres URLDirect Postgres URL on port 5432
Built-in authNo (use Clerk / Better Auth)Yes (if desired)No (use Clerk / Better Auth)
Built-in storageNo (use @nebutra/uploads)Yes (S3-compatible)No (use @nebutra/uploads)
pgvectorEnabled by defaultAvailable as extensionAvailable as extension
Prisma migration workflowChecked-in Postgres migrationsChecked-in Postgres migrationsChecked-in Postgres migrations

If your team relies heavily on per-PR database environments, choose a provider with database branching. If you want a single visual dashboard to inspect tables and run SQL without a separate tool, Supabase Studio is strong. If you already operate on PlanetScale or want its Postgres operational model, use PlanetScale Postgres rather than PlanetScale Vitess/MySQL for Sailor's core runtime.

PlanetScale Vitess/MySQL future path

PlanetScale Vitess/MySQL is a different database target, not a connection-string variant of the supported Postgres runtime. A future Sailor template for Vitess/MySQL would need its own contract:

  • a MySQL/Vitess Prisma schema or generated schema variant
  • a MySQL-compatible Prisma adapter strategy
  • a relationMode decision and, if using Prisma relation mode, explicit @@index coverage for relation scalar fields
  • a branch/deploy-request migration workflow that does not conflict with checked-in Postgres migrations
  • replacements for PostgreSQL-only features such as RLS and pgvector

Until that template exists, use PlanetScale Postgres for PlanetScale deployments.

FAQ

How is this guide?

Edit on GitHub

Last updated on

On this page