なぜPrismaから移行することを決めたのか?
SaaSの実プロジェクトにDrizzle ORMを導入して半年以上が経ち、一つの教訓を得ました。「シンプルさこそが至高である」ということです。以前、私たちのチームは利便性の高さからPrismaを非常に好んで使っていました。しかし、プロジェクトが拡大するにつれ、いくつかの問題が浮き彫りになりました。 VercelでのCold Startは、Prismaのバイナリファイルが重すぎるために2秒を超えることもありました。さらに、1,500行にも及ぶschema.prismaファイルは、Gitでの変更履歴の追跡を困難にさせました。
Drizzle ORMは、まさに私が求めていたものを解決してくれました。これは新しい抽象言語を作るのではなく、純粋なSQLの構文に近い形で記述でき、かつ100%のType-safeを保証します。最大の利点は、非常に軽量であることです。バイナリもオーバーヘッドもなく、クエリ速度はネイティブのドライバを使用するのとほぼ同等です。
Drizzle ORMの3つの柱
このツールを使いこなすには、次の3つのコンポーネントの仕組みを理解するだけで十分です:
- Drizzle ORM: クエリを記述するためのコアライブラリ. スマートで柔軟なクエリビルダーとして機能します。
- Drizzle Kit: マイグレーションを管理するCLIツール。
.tsコードと現在のデータベースを比較し、SQLファイルを自動生成します。 - Database Driver: Drizzleはデータベースに直接接続しません。
postgres.jsやmysql2などの既存のドライバを活用してパフォーマンスを最適化します。
Prismaのアプローチとは異なり、DrizzleはTypeScriptそのものでスキーマを定義します。これにより、変数や関数、プログラミングロジックを駆使して、スキーマを管理しやすい複数のモジュールに分割することが可能になります。
導入ガイド:インストールから最初のクエリまで
以下は、私が実際のプロジェクトでよく使用するPostgreSQLのセットアップ手順です。時間を節約するためにプロセスを簡略化しています。
ステップ1:初期化とインストール
必要なパッケージのインストールから始めましょう。古いpgライブラリよりもパフォーマンスに優れているpostgres.jsを選択します。
mkdir drizzle-demo && cd drizzle-demo
npm init -y
npm install drizzle-orm postgres
npm install -D typescript drizzle-kit @types/node
npx tsc --init
ステップ2:TypeScriptでスキーマを定義する
src/db/schema.tsファイルを作成します。IDEが即座にコード補完を行ってくれるため、スキーマの記述は非常に快適です。別途プラグインをインストールする必要もありません。
import { pgTable, serial, text, varchar, timestamp } from "drizzle-orm/pg-core";
export const users = pgTable("users", {
id: serial("id").primaryKey(),
fullName: text("full_name").notNull(),
email: varchar("email", { length: 255 }).notNull().unique(),
createdAt: timestamp("created_at").defaultNow(),
});
export const posts = pgTable("posts", {
id: serial("id").primaryKey(),
title: text("title").notNull(),
content: text("content").notNull(),
authorId: serial("author_id").references(() => users.id),
});
ここでの利点はモジュール化です。各テーブルを別々のファイルに分割してインポートすることができ、数十のテーブルを持つプロジェクトでも非常にクリーンに保てます。
ステップ3:マイグレーションの設定
ルートディレクトリにdrizzle.config.tsファイルを作成します。このファイルは、Drizzle Kitがスキーマを見つけ、変更履歴を保存する場所を指定します。
import { defineConfig } from "drizzle-kit";
export default defineConfig({
schema: "./src/db/schema.ts",
out: "./drizzle",
dialect: "postgresql",
dbCredentials: {
url: process.env.DATABASE_URL || "postgresql://user:pass@localhost:5432/db",
},
});
マイグレーションファイルを生成するには、次のコマンドを実行します:
npx drizzle-kit generate
Drizzleは純粋なSQLファイルを生成します。これを開いて直接確認したり修正したりすることが可能です。これは、Prismaが内部で管理する方法よりもはるかに透明性が高いです。
ステップ4:CRUDの実行
src/index.tsファイルで最初のクエリを試してみましょう。手動でgenerateコマンドを実行しなくても、すべてがType-safeな状態になっています。
import { drizzle } from "drizzle-orm/postgres-js";
import postgres from "postgres";
import { users } from "./db/schema";
import { eq } from "drizzle-orm";
const queryClient = postgres("postgresql://user:pass@localhost:5432/db");
const db = drizzle(queryClient);
async function run() {
// 新しいデータを追加
await db.insert(users).values({
fullName: "田中 太郎",
email: "[email protected]",
});
// TSの補完をフル活用してデータを取得
const result = await db.select().from(users);
console.log(result);
}
run();
本番環境で6ヶ月運用して得られた教訓
Drizzleを導入したことで、チームの作業効率は大幅に向上しました。特に強調したい実務上のポイントが3つあります:
- バンドルサイズが非常に軽量: Lambdaにデプロイする際のアプリケーション容量が約15MB削減されました。Cold startは2秒から300ミリ秒以下に短縮されました。
- デバッグが容易: クエリが遅い場合、
.toSQL()関数を使うだけで実際のSQL文が出力されます。これをそのままExplain Analyzeにかけて最適化に役立てることができます。 - 柔軟だが注意も必要: Drizzle Kitのカラム名変更(rename column)の処理は、時としてPrismaほどスマートではない場合があります。そのような時は、データの安全性を確保するためにマイグレーションSQLファイルを手動で修正しています。
おわりに
Drizzle ORMは、Prismaを完全に置き換える「銀の弾丸」ではありません。絶対的な安定性と巨大なコミュニティを優先するなら、依然としてPrismaは優れた選択肢です。しかし、スピード、軽量さ、そしてSQLを深く制御したいのであれば、ぜひDrizzleを試してみてください。まずは小さなマイクロサービスや個人プロジェクトから始めて、その違いを実感してから本格的に導入することをお勧めします。

