Database

Drizzle ORM and PostgreSQL setup in the Nuxt template.

The database layer is Integrated: Drizzle ORM on PostgreSQL via node-postgres, with auth and payment schemas. Postgres + Drizzle is the only wired path — the Prisma stub was removed.

Important files

FileRole
server/database/drizzle/client.tsCreates the Drizzle client: drizzle(runtimeConfig.databaseUrl)
server/database/index.tsRe-exports the client (and is the schema entry for Drizzle Kit)
server/database/drizzle/drizzle.config.tsDrizzle Kit config (dialect, schema, migrations out dir)
server/database/drizzle/schema/auth.tsuser, session, account, verification tables
server/database/drizzle/schema/payment.tssubscription, payment tables + enums
server/database/drizzle/service/payment.tsSmall data-access helper (createPayment)
server/database/drizzle/types.tsdrizzle-zod insert schema (PaymentInsertScheme)

Client

// server/database/drizzle/client.ts
import { drizzle } from "drizzle-orm/node-postgres";
const runtimeConfig = useRuntimeConfig();
const db = drizzle(runtimeConfig.databaseUrl!);
export default db;

Import it anywhere on the server as import db from "~~/server/database/drizzle/client". Better Auth consumes the auth schema through its Drizzle adapter (provider: "pg") in server/utils/auth.ts — see Authentication.

Schema

The auth schema holds Better Auth's user, session, account, and verification tables (the user table includes role and the admin plugin's banned/banReason/banExpires fields).

The payment schema holds:

  • subscription — one row per user (userId unique), with provider, status, period dates, and trial fields.
  • payment — one row per order, with amount, currency, status, provider, and a unique orderNo.

Both use Postgres enums (provider, order_status, subscription_status, plan_interval). See Payments for how rows are written.

Migration workflow

This template uses a generate/migrate workflow (not push). Drizzle Kit reads server/database/drizzle/drizzle.config.ts, which points schema at server/database/index.ts, writes migrations to server/database/migrations, and reads NUXT_DATABASE_URL from the Nuxt runtime config.

CommandWhat it does
npx drizzle-kit generateGenerate SQL migrations from the schema
npx drizzle-kit migrateApply pending migrations
npx drizzle-kit studioBrowse data in Drizzle Studio

The template ships without a committed server/database/migrations folder — your first generate creates it from the current schema. Commit the generated SQL so deploys apply the same migrations.

Add a table or field

Edit the schema

Add or change a table in server/database/drizzle/schema/*.ts. Make sure it is reachable from server/database/index.ts, since that file is the Drizzle Kit schema entry.

Generate and apply

npx drizzle-kit generate
npx drizzle-kit migrate

Keep Better Auth in sync

If you change auth tables, keep them compatible with Better Auth's expected columns. Prefer extending via the plugin/config rather than renaming core columns.

Production notes

  • drizzle(databaseUrl) uses a node-postgres pool. On serverless/edge platforms, point NUXT_DATABASE_URL at your provider's pooled connection string to avoid exhausting connections.
  • Run migrations as part of your deploy pipeline against the production database before traffic hits new code.
  • NUXT_ORM_PROVIDER is reserved but only drizzle is implemented.

On this page