Live demo — shared accounts, sample data, reset regularly. Don't enter anything real.Get the source
All posts
postgresdrizzletypescript

Why this starter uses Drizzle instead of Prisma

Both are good. Here's the specific tradeoff that made Drizzle the default for a starter meant to be read, not just run.

Prisma and Drizzle solve the same problem well. The choice here came down to one thing: what the schema looks like when you open the file.

Plain SQL you can actually read

Drizzle's schema is TypeScript that compiles to the SQL you'd have written by hand:

export const user = pgTable("user", {
  id: text("id").primaryKey(),
  email: text("email").notNull().unique(),
  role: text("role", { enum: ["user", "admin"] }).notNull().default("user"),
});

No custom DSL, no generated client to regenerate after every edit, no schema file that only a bundler-aware tool can parse. grep still works. That matters a lot in a starter meant to be forked, read end-to-end, and modified by someone who's never seen the codebase before.

Migrations you can read in a PR

npm run db:generate   # writes drizzle/NNNN_name.sql
npm run db:migrate    # applies pending migrations

The generated .sql file is the actual diff — reviewable in a pull request the same way application code is, not a binary lockfile you trust blindly.

Where Prisma still wins

Prisma's relation API and its Studio GUI are genuinely nicer for deeply nested queries and non-technical schema browsing. If your team is bigger than one and half of it isn't comfortable in SQL, that tradeoff might flip back in Prisma's favor — this starter's choice isn't a universal claim, just the right default for this shape of project.