Database and migrations
Postgres on NeonDB. Every table lives in the web schema and is declared with
webSchema.table() — never bare pgTable().
The only supported workflow
Section titled “The only supported workflow”# 1. Edit packages/db/src/schema.tsbun run db:generate # writes SQL + updates the journal# 2. READ the generated SQL in packages/db/migrations/bun run db:migrate:beta # apply to beta firstbun run db:migrate # then productionCustom SQL that Drizzle cannot infer:
npx drizzle-kit generate --customMigrations use the direct endpoint
Section titled “Migrations use the direct endpoint”db:migrate reads DATABASE_URL_DIRECT — the non-pooler host — and the script
aborts if it is given a -pooler URL.
Working in parallel
Section titled “Working in parallel”Two worktrees both generating migration 00NN collide in the journal.
Coordinate the number before you generate.
Things the schema will not tell you
Section titled “Things the schema will not tell you”updatedAtis not auto-managed. SetupdatedAt: new Date().toISOString()in every update.- Hold inserts take
pg_advisory_xact_lock(hashtext(id))inside the same transaction as the insert. On the pooled endpoint, a separate execute-then-insert can land on different connections and re-open double booking. bayarcash_transactionsandstripe_charges_importedexist in production but not inschema.ts. Read-only.- Supabase tooling is for the legacy mobile project only. It never points at
the
webschema.
The drizzle-schema skill covers adding a table or column end to end.
