Migrations
Configure Drizzle Kit and generate, apply, and seed SQL migrations
Configure Drizzle Kit
Create a
drizzle.config.ts next to
the package or app that owns the schema:
import "dotenv/config"
import { defineDrizzleConfig } from "@zeno-lib/db/config"
export default defineDrizzleConfig()Keep import "dotenv/config" here. Next.js loads .env* files for code running
inside the Next runtime, and Vercel provides environment variables during builds
and function execution, but Drizzle Kit runs this config as its own CLI process.
The import makes local .env values available before defineDrizzleConfig()
reads process.env.SUPABASE_DATABASE_URL.
The preset:
- Reads schema from
./src/schema.ts. - Writes migrations to
./supabase/migrations. - Uses the
postgresqldialect. - Reads
SUPABASE_DATABASE_URL. - Keeps Supabase's built-in roles marked as existing.
You can still pass Drizzle Kit overrides for package-specific credentials or paths, for example a separate migrations connection string:
import "dotenv/config"
import { defineDrizzleConfig } from "@zeno-lib/db/config"
export default defineDrizzleConfig({
dbCredentials: {
url: process.env.MIGRATIONS_DATABASE_URL ?? "",
},
})Generate migrations
With the package scripts
from installation in place, db:generate reads your TypeScript schema and writes
a SQL migration under supabase/migrations, and db:migrate applies generated
migrations to a database and records them in Drizzle Kit's migration table.
Author tables and RLS policies in your Drizzle schema, run db:generate
(drizzle-kit generate), review the generated SQL, and commit it under
supabase/migrations. Apply generated migrations with db:migrate
(drizzle-kit migrate) in environments where the database is not reset from
scratch.