Nuxt
Nuxt connects to DB9 through any standard PostgreSQL driver over pgwire. DB9 is PostgreSQL-compatible, so no special adapter is needed.
This guide shows how to set up a Nuxt 3 app with DB9 using Prisma and Drizzle.
Prerequisites
Section titled “Prerequisites”- A DB9 database (create one)
- Node.js 18+
- Nuxt 3+
Create a DB9 Database
Section titled “Create a DB9 Database”db9 create --name nuxt-appdb9 create prints the connection string, with the admin password, once — copy it from the Connection String: line. It has this shape:
postgresql://YOUR_TENANT_ID.admin:YOUR_PASSWORD@pg.d0000.db9.io:5432/postgresYOUR_TENANT_ID is the tenant ID prefix in the generated connection string. Copy the username from the Connection String: line printed by db9 create or from db9 db connect. The examples below use pg.db9.io:5433, which reaches the same server; either host and port works. db9 db status nuxt-app shows the connection string without the password; if you lose it, db9 db reset-password nuxt-app sets a new password and prints a new connection string.
Set the connection string as an environment variable:
DATABASE_URL="postgresql://YOUR_TENANT_ID.admin:YOUR_PASSWORD@pg.db9.io:5433/postgres?sslmode=require"npx nuxi@latest init nuxt-db9cd nuxt-db9npm install prisma@6 @prisma/client@6npx prisma initDefine your schema:
generator client { provider = "prisma-client-js"}
datasource db { provider = "postgresql" url = env("DATABASE_URL")}
model User { id Int @id @default(autoincrement()) email String @unique name String createdAt DateTime @default(now())}Push the schema and generate the client. prisma db push works for this initial creation
against an empty database; see Troubleshooting
before you change the schema later.
npx prisma db pushnpx prisma generateCreate a server utility to share the Prisma instance:
import { PrismaClient } from '@prisma/client';
const prisma = new PrismaClient();
export default prisma;npx nuxi@latest init nuxt-db9cd nuxt-db9npm install drizzle-orm pgnpm install -D drizzle-kit @types/pgDefine your schema:
import { pgTable, serial, varchar, timestamp } from 'drizzle-orm/pg-core';
export const users = pgTable('users', { id: serial('id').primaryKey(), email: varchar('email', { length: 255 }).unique().notNull(), name: varchar('name', { length: 100 }).notNull(), createdAt: timestamp('created_at', { withTimezone: true }).defaultNow(),});Create a server utility for the database connection:
import { drizzle } from 'drizzle-orm/node-postgres';import { Pool } from 'pg';
const pool = new Pool({ connectionString: process.env.DATABASE_URL,});
export const db = drizzle(pool);Server API Route
Section titled “Server API Route”import prisma from '~/server/utils/prisma';
export default defineEventHandler(async () => { return await prisma.user.findMany({ orderBy: { createdAt: 'desc' }, });});import prisma from '~/server/utils/prisma';
export default defineEventHandler(async (event) => { const body = await readBody(event); return await prisma.user.create({ data: { email: body.email, name: body.name, }, });});import { db } from '~/server/utils/db';import { users } from '~/server/db/schema';
export default defineEventHandler(async () => { return await db.select().from(users).orderBy(users.createdAt);});import { db } from '~/server/utils/db';import { users } from '~/server/db/schema';
export default defineEventHandler(async (event) => { const body = await readBody(event); const result = await db.insert(users).values({ email: body.email, name: body.name, }).returning(); return result[0];});Composable Usage
Section titled “Composable Usage”Call the API routes from a page using useFetch:
<script setup lang="ts">const { data: users, refresh } = await useFetch('/api/users');
async function addUser() { await $fetch('/api/users', { method: 'POST', body: { name: 'Alice', email: 'alice@example.com' }, }); await refresh();}</script>
<template> <div> <button @click="addUser">Add User</button> <ul> <li v-for="user in users" :key="user.id"> {{ user.name }} ({{ user.email }}) </li> </ul> </div></template>Production Notes
Section titled “Production Notes”- Server-side only: All database access happens in the
server/directory. Nuxt server routes and utilities never ship to the client, so your connection string stays private. - Host and port:
pg.db9.io:5433and thepg.d0000.db9.io:5432thatdb9 createprints reach the same server; port5432works on either host. - TLS: Always include
sslmode=requirein your connection string for DB9’s hosted service. - Nitro server preset: Use the Node.js preset for deployment. Edge presets (Cloudflare Workers, Deno Deploy) do not support raw TCP connections required by pgwire. Set
nitro.presetinnuxt.config.ts:
export default defineNuxtConfig({ nitro: { preset: 'node-server', },});Troubleshooting
Section titled “Troubleshooting”ECONNREFUSED on port 5432
Section titled “ECONNREFUSED on port 5432”DB9 accepts port 5432 as well as 5433, so the client is not reaching DB9 at all. A refusal from localhost or 127.0.0.1 means the connection string never reached the driver — check that DATABASE_URL is set in the process that opens the connection.
Edge preset not supported
Section titled “Edge preset not supported”DB9 requires pgwire (TCP), which is not available in edge runtimes. Switch to the node-server or node-cluster Nitro preset.
Run prisma db push only once
Section titled “Run prisma db push only once”prisma db push works for the initial schema creation against an empty database. Do not run
it again once the tables exist: Prisma does not recognise DB9’s spelling of a serial column’s
default and plans to recreate the sequence behind each autoincrement() id. For a table named
after its model, as here, that second push reports success while pointing id at a new sequence
that starts at 1, so inserts into a table that already has rows fail with
23505 duplicate key value. prisma migrate dev additionally fails at P3014, because DB9
rejects the hyphenated name Prisma gives its shadow database.
Create the initial schema with prisma db push, then apply later changes with raw SQL. See
A second db push fails on autoincrement() ids.
Environment variables not available in Nitro
Section titled “Environment variables not available in Nitro”Nitro reads .env files automatically in development. For production, set DATABASE_URL through your hosting platform’s environment variable configuration. If needed, add runtimeConfig in nuxt.config.ts:
export default defineNuxtConfig({ runtimeConfig: { databaseUrl: process.env.DATABASE_URL, },});Then access it in server routes with useRuntimeConfig().databaseUrl.
Next Pages
Section titled “Next Pages”- Prisma — full Prisma integration guide
- Drizzle — full Drizzle integration guide
- Connect — connection strings and authentication
- Production Checklist — deployment readiness