My new go-to data layer is Drizzle + Turso
Typescript + Drizzle + Turso is a powerful delight
I think my new tech stack is bun/node
+ drizzle
+ turso
. The purpose of this article is to prove this for myself and document the setup.
First off, some definitions -
bun
andnode
are both server side runtimes of theJavascript
programming language.Bun
can also runTypescript
natively.drizzle
is anORM
, orObject Relational Mapper
that uses Typescript to define database architecture and relationships, and serves as the API for interacting with said database. - https://orm.drizzle.team/turso
is a cloud database solution that runs a forked version of SQLite. I like turso because it's easy to use and the free tier is the most generous I've seen on the internet. - https://docs.turso.tech/introduction
In short, I like this stack for the following reasons -
- I am most comfortable writing applications in Typescript
- As far as I've seen,
drizzle
serves wonderfully as a frontend for your database inturso
- The entire stack is simple to set up!
A demo -
We're going to take this from the top. Steps -
- Spin up a
bun
application - install dependencies to allow usage of
drizzle
andturso
- create
turso
database - create the database schema
- perform basic CRUD operations to confirm setup!
Cool. Drizzle has great documentation on how to do exactly this here.
Spinning up the Bun application
zsh
I accept all the basic settings and have my project setup.
Installing dependencies
Bun dependencies
bash
Turso CLI -
brew install tursodatabase/tap/turso
Create Turso database
Now that we've got everything installed, it's time to use the turso CLI
to make our database.
At this point it's really just following the steps here - https://orm.drizzle.team/learn/tutorials/drizzle-with-turso#setup-turso-and-drizzle-orm
Within the documentation, we -
- Create our new database in turso
- get our connection keys
- wire put them in our
.env
file and set up the boilerplate connection code
Create the database schema
We can continue referencing this - https://orm.drizzle.team/learn/tutorials/drizzle-with-turso#setup-turso-and-drizzle-orm
During this step, we -
- create the database schema in typescript with
drizzle
using the following syntax -
typescript
- create a top level
drizzle.config.ts
file to house your global drizzle settings.
typescript
- generate the migrations file for the database (the change log from which it will build) and then apply those migrations to create or modify database table(s).
Confirm success
First off, now that I've applied the database migrations, I can use drizzle studio
to serve as a UI for my database and confirm the tables I expect to exist do indeed exist.
bunx drizzle-kit studio
This spins up a UI at https://local.drizzle.studio
, and I can clearly see that my migrations were applied, based on the existence of the posts
and users
table.
Not only can I see my data or currently lack thereof, but I can also run SQL directly against the database via the SQL runner
, or write drizzle TS api
code in Drizzle Runner
. I foresee that being super helpful in situations where you want to test your application queries without needing to run your application. Build the queries first in Drizzle runner
and then insert them into your application with confidence.
Next I'm going to add a couple of users and give them a couple of posts, and then query the database for posts by user. This should be a pretty simple Hello World
sort of confirmation that this has all worked.
Creating users
typescript
My index.ts
file at root level is now
typescript
So when I run the app, it will add this user to the database. The great thing with the drizzle
+ typescript
integration is that as soon as I removed a required field, it alerted me that it was missing. This way, the source of truth is the database schema, and drizzle
enforces it in the application layer.
bun index.ts
annnnd, boom -
Now let's make some a post.
typescript
typescript
Tadaaaa -
I can also now see the foreign key relationship in in the users
table.
And now we confirm everything returns as expected in the application -
typescript
console logs -
json
And just like that, we're fully wired up. I'm still getting over how painless this process has been, and am excited by the potential.