Database
Schema Definition
Define your database schema with Drizzle ORM
Your database schema is defined in packages/db/src/schema.ts. Drizzle uses TypeScript to define tables, columns, and relations.
Defining Tables
import {
,
,
,
,
,
} from "drizzle-orm/pg-core"
declare const : { : unknown }
export const = ("Post", {
: ("id").primaryKey(),
: ("title", { : 255 }).notNull(),
: ("content"),
: ("published").default(false).notNull(),
: ("authorId")
.notNull()
.references(() => ., { : "cascade" }),
: ("createdAt", { : "date" }).defaultNow().notNull(),
: ("updatedAt", { : "date" }).defaultNow().notNull()
}, () => [
("Post_authorId_idx").on(.authorId)
])Column Types
Common PostgreSQL column types:
| Drizzle | PostgreSQL | Example |
|---|---|---|
text() | TEXT | text("name") |
varchar() | VARCHAR(n) | varchar("slug", { length: 64 }) |
boolean() | BOOLEAN | boolean("active").default(true) |
integer() | INTEGER | integer("count") |
timestamp() | TIMESTAMP | timestamp("createdAt", { mode: "date" }) |
json() | JSON | json("metadata") |
jsonb() | JSONB | jsonb("settings") |
Enums
Define PostgreSQL enums for constrained values:
import { , } from "drizzle-orm/pg-core"
import { } from "drizzle-orm/pg-core"
export const = ("status", ["draft", "published", "archived"])
export const = ("Post", {
: ("id").primaryKey(),
: ("status").default("draft").notNull()
})Relations
Define relations for type-safe joins:
import { , } from "drizzle-orm/pg-core"
import { } from "drizzle-orm"
declare const : { : unknown }
declare const : unknown
export const = ("Post", {
: ("id").primaryKey(),
: ("authorId").notNull()
})
export const = (, ({ , }) => ({
: (, {
: [.authorId],
: [.]
}),
: ()
}))Indexes
Add indexes for frequently queried columns:
export const = ("Post", {
: ("id").primaryKey(),
: ("slug").notNull(),
: ("authorId").notNull(),
: ("createdAt").defaultNow().notNull()
}, () => [
("Post_slug_idx").on(.slug),
("Post_authorId_idx").on(.authorId),
("Post_createdAt_idx").on(.createdAt)
])Unique Constraints
import { , , } from "drizzle-orm/pg-core"
export const = ("Post", {
: ("id").primaryKey(),
: ("slug").notNull()
}, () => [
("Post_slug_key").on(.slug)
])Inferred Types
Export TypeScript types from your schema:
export type = typeof .$inferSelect
export type = typeof .$inferInsertUse these throughout your app:
import type { , } from "@repo/db"
import { , } from "@repo/db"
async function (: ): <> {
const [] = await .insert().values().returning()
return
}Default Schema
The starter includes these tables:
// User authentication
export const = ("User", { /* ... */ })
export const = ("Account", { /* ... */ })
export const = ("Session", { /* ... */ })
export const = ("Verification", { /* ... */ })
// Team management
export const = ("Team", { /* ... */ })
export const = ("TeamMember", { /* ... */ })All relations are pre-configured for the auth and team systems.
Best Practices
- Use descriptive table names - PascalCase for table names (
"User","Post") - Add timestamps - Include
createdAtandupdatedAton all tables - Index foreign keys - Always index columns used in relations
- Use references - Define foreign key constraints with
references() - Export types - Create
$inferSelectand$inferInserttypes for each table