Mengintegrasikan Drizzle ORM ke proyek Hono: setup dengan Cloudflare D1 atau SQLite, mendefinisikan schema Drizzle, query builder type-safe, menggunakan bindings di Hono, dan connection pooling untuk non-edge.

Setelah di episode 7 kita memahami middleware, pada episode ini kita akan mengintegrasikan database ke proyek Hono menggunakan Drizzle ORM — TypeScript-first ORM yang ringan (~7KB), zero dependencies, dan kompatibel dengan Cloudflare D1, Neon, dan Turso.
Keduanya dibangun dengan filosofi yang sama: TypeScript-first, performa tinggi, dan minimalis. Drizzle menggunakan SQL-like query builder, sementara Hono memastikan tipe dari query secara otomatis terekspos ke RPC client.
bun add drizzle-orm
bun add -D drizzle-kitUntuk Cloudflare D1:
bun add @libsql/client[[d1_databases]]
binding = "DB"
database_name = "my-database"
database_id = "your-database-id"import { sqliteTable, text, integer } from 'drizzle-orm/sqlite-core'
export const users = sqliteTable('users', {
id: integer('id').primaryKey({ autoIncrement: true }),
name: text('name').notNull(),
email: text('email').notNull().unique(),
createdAt: text('created_at').notNull().default(''),
})
export const posts = sqliteTable('posts', {
id: integer('id').primaryKey({ autoIncrement: true }),
title: text('title').notNull(),
content: text('content').notNull(),
authorId: integer('author_id').notNull().references(() => users.id),
})import { Hono } from 'hono'
import { drizzle } from 'drizzle-orm/d1'
import * as schema from './db/schema'
import { eq } from 'drizzle-orm'
type Bindings = {
DB: D1Database
}
const app = new Hono<{ Bindings: Bindings }>()
app.get('/users', async (c) => {
const db = drizzle(c.env.DB)
const users = await db.select().from(schema.users)
return c.json(users)
})
app.get('/users/:id', async (c) => {
const db = drizzle(c.env.DB)
const id = Number(c.req.param('id'))
const [user] = await db.select().from(schema.users).where(eq(schema.users.id, id))
return user ? c.json(user) : c.json({ error: 'Not found' }, 404)
})
app.post('/users', async (c) => {
const db = drizzle(c.env.DB)
const body = await c.req.json()
const [created] = await db.insert(schema.users).values(body).returning()
return c.json(created, 201)
})interface Bindings {
DB: D1Database
MY_KV: KVNamespace
}
const app = new Hono<{ Bindings: Bindings }>()
app.get('/data', async (c) => {
const db = drizzle(c.env.DB)
const cached = await c.env.MY_KV.get('data')
if (cached) return c.json(JSON.parse(cached))
const data = await db.select().from(schema.users)
await c.env.MY_KV.put('data', JSON.stringify(data), { expirationTtl: 3600 })
return c.json(data)
})import { Pool } from 'pg'
import { drizzle } from 'drizzle-orm/node-postgres'
const pool = new Pool({
connectionString: process.env.DATABASE_URL,
max: 20,
})
const db = drizzle(pool)import { Database } from 'bun:sqlite'
import { drizzle } from 'drizzle-orm/bun-sqlite'
const sqlite = new Database('local.db')
const db = drizzle(sqlite)Warning
Untuk Cloudflare D1, tidak ada connection pooling — D1 dibangun untuk serverless dan menangani connection management secara otomatis. Untuk PostgreSQL atau MySQL, selalu gunakan connection pooling.
Pada episode 8 ini, kalian telah mengintegrasikan Drizzle ORM ke proyek Hono — dari setup hingga query builder type-safe dan bindings.
Inti yang harus dibawa pulang:
db.select(), db.insert(), db.update(), db.delete().c.env.DB untuk akses database di Cloudflare Workers.Di episode 9 selanjutnya kita akan memahami RPC mode: type-safe client calls — setup RPC client, type inference, dan kapan pakai RPC vs REST. Sampai jumpa di episode 9!