raxel.studio

Docs / Database

Database

The starter uses Drizzle ORM with Postgres. Schema is TypeScript; migrations are generated by Drizzle Kit; the dev workflow is db push.

Layout #

db/
  schema/          — schema definitions, one file per domain
  index.ts         — exports the `db` client
drizzle.config.ts  — Drizzle Kit config (driver, schema path, output dir)

The db client is the only thing your app imports from db/. Server code calls it directly; client code never touches the database.

Dev workflow: db push #

For local development:

pnpm db:push

This compares your TypeScript schema to the local database and applies the diff. Fast iteration; no migration files generated.

Production workflow: migrations #

For environments you care about (staging, prod):

pnpm db:generate    # writes a new migration file under db/migrations/
pnpm db:migrate     # applies pending migrations

Commit migration files. Review them before merging — Drizzle Kit generates the SQL but you own it.

Adding a table #

  1. Define it in a new file under db/schema/:
import { pgTable, text, timestamp } from "drizzle-orm/pg-core";
 
export const widgets = pgTable("widgets", {
  id: text("id").primaryKey(),
  name: text("name").notNull(),
  createdAt: timestamp("created_at").defaultNow().notNull(),
});
  1. Export it from db/schema/index.ts.

  2. Run pnpm db:push in dev (or db:generate + db:migrate for prod).

  3. Use it:

import { db } from "@/db";
import { widgets } from "@/db/schema";
 
const all = await db.select().from(widgets);

Connection pooling #

The starter uses the postgres driver (not pg), which handles pooling internally. In serverless environments (Vercel, etc.), set DATABASE_URL to a pooler-aware connection string.

Seeding #

There's no built-in seed script. If you need one, add scripts/seed.ts and a pnpm seed entry — the pattern is unopinionated by design.