Drizzle foundations

Choose Drizzle with open eyes

Understand what an ORM gives you, what Drizzle deliberately leaves visible, and when plain SQL may still be the better tool.

An ORM (object-relational mapper) connects the objects in your code to the rows in your database. The promise many ORMs make is that you can stop thinking about SQL. You can’t. Sooner or later a query gets slow, or returns the wrong rows, and the SQL is what you need to read.

Drizzle makes a smaller promise. You describe your tables in TypeScript. You build queries with methods that look like SQL: select, from, where, orderBy. TypeScript checks column names and value types while you type. The database still does what a database does: constraints, transactions, indexes, query plans.

I like this trade. When something goes wrong, I can print the SQL Drizzle generated and reason about it. Nothing is hidden behind a magic layer.

What we will build

Through the course we build a small notes database. Two tables: users and notes. Every note belongs to one user.

That’s enough to touch everything that matters: schema, migrations, inserts, filtered reads, ownership checks, relations, transactions, and tests.

We use SQLite through the driver built into Node.js, so there is no database server to install. The Drizzle concepts are the same for PostgreSQL, MySQL, and Cloudflare D1. Only the schema imports and the connection code change, which we cover in the last lesson.

What TypeScript checks, and what it doesn’t

This is the distinction I want you to keep in mind for the whole course.

TypeScript can tell you that notes.titel is a typo. It can tell you that authorId must be a number. It can tell you an insert is missing a required field.

TypeScript cannot tell you that two users have the same email, that a note points to a user who was deleted, or that a query scans the whole table. Only the database, or a test that runs against a real database, can verify those.

Drizzle helps with the first group. We still have to design for the second group.

When plain SQL is better

Sometimes a query is clearer as SQL. Reports with several joins and aggregates are a common case. Drizzle ships an sql template tag for this, and you can mix it with the query builder.

So this is not an all-or-nothing choice. My advice is to use the query builder by default, because the types catch typos and shape mistakes for free. Drop to sql when the builder makes a query harder to read than the SQL would be.

Before moving on, take one table and three queries from an application you know. For each query, write down what TypeScript could verify and what only the database can. That list is the mental model for the rest of the course.

Lesson completed