Drizzle ORM + better-sqlite3 CRUD: working versions (tested 2026-10-15)
Typed schema, migrations-free table creation and CRUD with Drizzle on an in-memory SQLite database.
passed1 passed · 0 failed2026-10-15 11:34 UTC- Status
- passed
- Last passed
- 2026-10-15 11:34 UTC
- Tests
- 1 / 1
- Language
- TypeScript
- Runtime
- node v22.23.3
npm install --no-audit --no-fund --ignore-scripts=false npm test
node v22.23.3 linux 6.17.0-1022-azure x64 runner: github-actions 38728226240
The code
Exactly the files that passed. Your agent can pull them with get_recipe("drizzle-sqlite-crud") (install), or see them on GitHub.
{
"name": "drizzle-sqlite-crud",
"private": true,
"type": "module",
"scripts": {
"test": "node --import tsx --test test/*.test.ts"
},
"dependencies": {
"drizzle-orm": "0.45.4",
"better-sqlite3": "12.11.1"
},
"devDependencies": {
"tsx": "4.23.15",
"@types/node": "24.19.2",
"@types/better-sqlite3": "9.6.0"
}
}
import Database from "better-sqlite3";
import { drizzle } from "drizzle-orm/better-sqlite3";
import { sqliteTable, integer, text } from "drizzle-orm/sqlite-core";
import { eq } from "drizzle-orm";
export const todos = sqliteTable("todos", {
id: integer("id").primaryKey({ autoIncrement: true }),
title: text("title").notNull(),
done: integer("done", { mode: "boolean" }).notNull().default(false),
});
export function createDb(file = ":memory:") {
const sqlite = new Database(file);
sqlite.exec(`CREATE TABLE IF NOT EXISTS todos (
id INTEGER PRIMARY KEY AUTOINCREMENT, title TEXT NOT NULL, done INTEGER NOT NULL DEFAULT 0)`);
return drizzle(sqlite);
}
export type Db = ReturnType<typeof createDb>;
export const addTodo = (db: Db, title: string) => db.insert(todos).values({ title }).returning().get();
export const listTodos = (db: Db) => db.select().from(todos).all();
export const completeTodo = (db: Db, id: number) => db.update(todos).set({ done: true }).where(eq(todos.id, id)).returning().get();
export const deleteTodo = (db: Db, id: number) => db.delete(todos).where(eq(todos.id, id)).run();
import { test } from "node:test";
import assert from "node:assert/strict";
import { createDb, addTodo, listTodos, completeTodo, deleteTodo } from "../src/db.ts";
test("insert, update, list, delete", () => {
const db = createDb();
const t = addTodo(db, "write recipe");
assert.equal(t.done, false);
assert.equal(completeTodo(db, t.id).done, true);
assert.equal(listTodos(db).length, 1);
deleteTodo(db, t.id);
assert.equal(listTodos(db).length, 0);
});
Connect to ProvenPin
Add the free MCP server so your agent can pull this recipe and others like it. Same setup as the docs.
claude mcp add --transport http provenpin https://mcp.provenpin.com/mcp
{ "mcpServers": { "provenpin": { "url": "https://mcp.provenpin.com/mcp" } } }{ "servers": { "provenpin": { "type": "http", "url": "https://mcp.provenpin.com/mcp" } } }{ "mcpServers": { "provenpin": { "serverUrl": "https://mcp.provenpin.com/mcp" } } }{ "mcpServers": { "provenpin": { "type": "streamableHttp", "url": "https://mcp.provenpin.com/mcp" } } }Any other MCP client: Streamable HTTP at https://mcp.provenpin.com/mcp. No API key, no signup.
Related stacks
Drizzle ORM + drizzle-zod validated inserts on SQLite
Generate Zod insert and select schemas from Drizzle tables with drizzle-zod, refine them, and validate input before inserting into SQLite.
Hono + Drizzle ORM + SQLite REST API (Vitest)
CRUD REST API in Hono backed by Drizzle ORM on better-sqlite3, with Zod validation, tested with Vitest and app.request().
Kysely + better-sqlite3 typed queries
Type-safe SQL with Kysely on SQLite, including a schema migration, joins and a transaction.
Prisma 7 + SQLite via better-sqlite3 adapter
Prisma Client 7 with the better-sqlite3 driver adapter, schema push and relational queries on a local SQLite file.
All Drizzle ORM recipesAll better-sqlite3 recipesAll SQLite recipes