StartupKitstartupkit
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

packages/db/src/schema.ts
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:

DrizzlePostgreSQLExample
text()TEXTtext("name")
varchar()VARCHAR(n)varchar("slug", { length: 64 })
boolean()BOOLEANboolean("active").default(true)
integer()INTEGERinteger("count")
timestamp()TIMESTAMPtimestamp("createdAt", { mode: "date" })
json()JSONjson("metadata")
jsonb()JSONBjsonb("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 .$inferInsert

Use 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

  1. Use descriptive table names - PascalCase for table names ("User", "Post")
  2. Add timestamps - Include createdAt and updatedAt on all tables
  3. Index foreign keys - Always index columns used in relations
  4. Use references - Define foreign key constraints with references()
  5. Export types - Create $inferSelect and $inferInsert types for each table

On this page