Quickstart: Drizzle ORM
Last updated 2 November 2026In Getting started
From sign-in to a first Drizzle ORM query on a Tonbo database.
Run it from your laptop or any machine with Node.js 22.19 or later and internet access, with nothing to allowlist, on Linux (x64 or arm64) or macOS on Apple silicon; on any other platform, such as an Intel Mac, build the package’s SQLite extension from source first (see Requirements).
Sign in
Sign in at tonbo.dev with GitHub or Google. A new account asks you to choose a username: it names your personal account, which holds your databases, streams and keys, and appears in the console’s addresses. You can change it once every 90 days.
Create a database
Create a database named notes. It goes to the default region, us-east-1, unless you choose another (see Regions): pick the one nearest where your program runs. With the CLI, name it with --region, as in tonbo database create notes --region ap-southeast-1.
- Open Databases in the console.
- Choose Create database and name it
notes.
npm i -g @tonbo/cli
tonbo login
tonbo database create notestonbo login signs you in through a browser on the same machine. Over SSH, or on a machine without a browser, it prints a short code instead: open https://tonbo.dev/cli/device in a browser on any computer where you are signed in, enter the code, check the computer name and approve (tonbo login --device asks for the code anywhere). For non-interactive use, such as CI, set TONBO_API_KEY to a key that acts as you and is not narrowed, created in the console under API keys, and the CLI uses it instead.
With a key that acts as you and is not narrowed, in TONBO_API_KEY: create one in the console under API keys without narrowing it. The next step’s key is narrowed, and a narrowed key never creates databases.
curl -sS https://api.tonbo.dev/v1/databases \
-H "Authorization: Bearer $TONBO_API_KEY" \
-H "Idempotency-Key: $(uuidgen)" \
-H "Content-Type: application/json" \
-d '{"name":"notes"}'It answers 201 once the database is active, or 202 while it is still being created.
The database is creating for a moment, then active. Node.js code opens it by name, and Python code by its URL, which tonbo database show notes and the console show (see Regions and URLs).
Create an API key
Give the program its own key, narrowed to notes: it reads and writes only that database, and may name one that does not exist yet. A key that acts as you and is not narrowed reaches every database and stream you can in its account (see What a key can reach).
- In the console, choose API keys in the sidebar.
- Choose New API key and narrow it to the database
notes. - Copy the key. It starts with
tbo_and is shown once.
tonbo api-key create notes-app --database notesIt prints the key once, as TONBO_API_KEY=..., ready for the program’s environment. Put it before the command that runs the program, as the next step does, rather than exporting it in your shell: the CLI reads TONBO_API_KEY too, and would then act with the narrowed key.
On this machine, after tonbo login, a Node.js program can also open its databases with no key at all: open() falls back to your login (see Connect). Python does not, and the narrowed key is what any program uses anywhere else.
Install the packages
npm install --save-exact @tonbo/sdk@1.0.0 @tonbo/sqlite-ursula@0.11.4 drizzle-orm@1.0.0-rc.5
npm install --save-dev drizzle-kit@1.0.0-rc.5Check that npm added the prebuilt extension for your platform:
npm ls --all | grep @tonbo/sqlite-ursula-It prints the extension’s package, such as @tonbo/sqlite-ursula-darwin-arm64 on a Mac with Apple silicon. If it prints nothing, npm skipped that optional package: install again without --omit=optional, or, on a platform with no prebuilt extension, build it from source (see Requirements).
Define the schema
import { integer, sqliteTable, text } from "drizzle-orm/sqlite-core";
export const todos = sqliteTable("todos", {
id: integer().primaryKey(),
title: text().notNull(),
done: integer({ mode: "boolean" }).notNull(),
});import { defineConfig } from "drizzle-kit";
export default defineConfig({
dialect: "sqlite",
schema: "./schema.mjs",
out: "./drizzle",
});Generate the migration from it:
npx drizzle-kit generateOpen, migrate and query
Save this as app.mjs:
import { openDatabase } from "@tonbo/sdk/database";
import { eq } from "drizzle-orm";
import { drizzle } from "drizzle-orm/node-sqlite";
import { migrate } from "drizzle-orm/node-sqlite/migrator";
import { todos } from "./schema.mjs";
const client = await openDatabase("notes");
const db = drizzle({ client });
migrate(db, { migrationsFolder: "./drizzle" });
await db.insert(todos).values({ title: "write the docs", done: false });
const pending = await db.select().from(todos).where(eq(todos.done, false));
await client.synced();
console.log(pending);Run it with the key from the API key step:
TONBO_API_KEY=tbo_... node app.mjsIt prints the pending todos. Run it again, on this machine or another: the migration is already applied, and the rows are there.
Add it to a project
In a project of your own, with the program’s API key in TONBO_API_KEY where the project keeps its secrets, never in its code:
- Create the database with
tonbo database create notes, signed in withtonbo login, or in the console.tonbo database show notesprintsState:activeonce it is ready. - Install, keeping the exact versions:
npm install --save-exact @tonbo/sdk@1.0.0 @tonbo/sqlite-ursula@0.11.4 drizzle-orm@1.0.0-rc.5 npm install --save-dev drizzle-kit@1.0.0-rc.5npm ls --all | grep @tonbo/sqlite-ursula-then prints the prebuilt extension for your platform. - Hand Drizzle the database opened by name, with
openDatabasefrom@tonbo/sdk/databaseanddrizzlefromdrizzle-orm/node-sqlite:const client = await openDatabase("notes"); const db = drizzle({ client });Run the migrations from the program withmigrate(see Drizzle ORM). - Await
client.synced()before anything outside the process acts on a commit: until then the commit is only on this machine.
One process writes a database at a time: the last one to open it (see When two instances run).