Database & Migrations

Define PostgreSQL schemas with Drizzle ORM in VitNode plugins, generate migrations, and execute queries.

VitNode uses PostgreSQL and Drizzle ORM. Plugins define typed schema files, compile them into SQL migrations, and query tables via c.get("db").

Quick start

1. Define the Schema

Create a database model in plugins/{plugin}/src/database/{table}.ts:

plugins/reactions/src/database/reactions.ts
import { camelCase } from "drizzle-orm/pg-core"

export const reactions = camelCase.table.withRLS("reactions", (t) => ({
  id: t.serial().primaryKey(),
  itemId: t.integer().notNull(),
  emoji: t.varchar({ length: 32 }).notNull(),
  createdAt: t.timestamp().notNull().defaultNow(),
}))

2. Query in an API Route

Access the typed Drizzle instance using c.get("db"):

plugins/reactions/src/api/modules/reactions/routes/get.route.ts
import { buildRoute } from "@vitnode/core/api/lib/route"
import { reactions } from "@/database/reactions"

export const getReactionsRoute = buildRoute({
  pluginId: "reactions",
  route: {
    method: "get",
    path: "/",
    responses: { 200: { description: "List of reactions" } },
  },
  handler: async (c) => {
    const rows = await c.get("db").select().from(reactions)
    return c.json(rows)
  },
})

3. Build & Apply Migrations

Build and migrate
bun run build:plugins && bun run db:migrate
pnpm build:plugins && pnpm db:migrate
npm run build:plugins && npm run db:migrate

build:plugins compiles your TypeScript models and exports, and db:migrate updates PostgreSQL.


Migration Commands

CommandAction
pnpm db:generateInspects schema diffs and writes timestamped SQL migrations
pnpm db:migrateApplies pending migrations against the target database
pnpm db:studioOpens Drizzle Studio to inspect and edit database rows visually

Content Engine Alternative

If your table represents an editorial entity (articles, FAQs, products), consider Content Engine to generate your Drizzle table, API routes, and AdminCP screens from one definition.

Learn More