オプション
家 Skill ウェブ開発 drizzle-orm

実行時のオーバーヘッドがゼロの、TypeScript 向け型安全な SQL ORM

...すべて拡張します
70
更新された時間 2026年6月29日

概要drizzle-orm

Drizzle ORMは、実行時のオーバーヘッドをゼロに抑えつつ、SQLデータベースとの型安全なやり取りを実現するように設計された、TypeScriptを第一に考えた最新のオブジェクトリレーショナルマッピング(ORM)ライブラリです。 リレーショナルデータベースを扱う際に発生しがちな実行時エラーや型不一致の問題を、コンパイル時の型チェックと、開発者が TypeScript 内で直接使用できる SQL 風の構文を提供することで解決します。これにより、データベース操作の予測可能性が高まり、効率性と依存関係の最小化が重要なサーバーレスやエッジランタイム環境におけるバグの発生確率が低減されます。

このORMは、いくつかの重要な機能と能力を備えています。PostgreSQL、MySQL、SQLiteを含む複数のデータベースをサポートしており、開発者はプロジェクトに適したドライバーを選択できます。Drizzle ORMは、さまざまな列型がTypeScriptの型に直接マッピングされる柔軟なスキーマ定義システムを提供し、クエリ、挿入、更新における強力な型付けを可能にします。 また、1対多の関係など、テーブル間の関係を定義する機能も備えており、SELECTおよびINSERT操作の両方において型推論をサポートしています。さらに、Drizzle Kitをマイグレーションに使用できるため、時間の経過に伴うデータベーススキーマの変更管理が容易になります。依存関係ゼロの設計により、プロジェクトへの軽量な統合と、リソースが制約された環境での最適なパフォーマンスが保証されます。

対象ユーザーには、SQLデータベースと連携し、強力な型安全性と予測可能な動作を必要とするアプリケーションを構築するTypeScript開発者が含まれます。 Drizzle ORMは、サーバーレスアプリケーションやエッジ関数、あるいはパフォーマンスと実行時のオーバーヘッドの最小化が重要なプロジェクトを開発するユーザーにとって特に有用です。単純なCRUDアプリケーションから、リレーショナルデータモデルや高度なクエリパターンを用いたより複雑なシステムに至るまで、幅広いシナリオに適しており、TypeScriptの型システムを活用しながら、データベースとのやり取りに対して信頼性が高く保守しやすいアプローチを提供します。

よくある質問

Drizzle ORMのインストールと設定方法は?

npm を使用して `npm installdrizzle-orm` と実行し、コア ORM をインストールした後、PostgreSQL 用の `pg` や MySQL 用の `mysql2` など、使用するデータベースに適したデータベースドライバをインストールします。マイグレーションを行う場合は、開発依存関係として `drizzle-kit` をインストールしてください。

Drizzle ORMはどのデータベースに対応していますか?

Drizzle ORMは、それぞれのデータベースドライバーを通じて、PostgreSQL、MySQL、およびSQLiteをサポートしています。

Drizzle ORMは実行時のオーバーヘッドを生じますか?

いいえ、Drizzle ORMは実行時のオーバーヘッドがゼロになるように設計されており、安全性と正確性を確保するためにコンパイル時の型チェックに依存しています。

テーブル間のリレーションシップを定義できますか?

はい、Drizzle ORMは「1対多」などの関係の定義をサポートしており、TypeScriptでリレーショナルデータを安全にモデル化できます。

Drizzle ORMはサーバーレス環境やエッジ環境に適していますか?

はい。依存関係を一切持たない設計と効率的なクエリ処理により、サーバーレスおよびエッジランタイムでのパフォーマンスが最適化されています。

GitHubで見る

Drizzle ORM

Modern TypeScript-first ORM with zero dependencies, compile-time type safety, and SQL-like syntax. Optimized for edge runtimes and serverless environments.

Quick Start

Installation

# Core ORMnpm install drizzle-orm# Database driver (choose one)npm install pg            # PostgreSQLnpm install mysql2        # MySQLnpm install better-sqlite3 # SQLite# Drizzle Kit (migrations)npm install -D drizzle-kit

Basic Setup

// db/schema.tsimport { pgTable, serial, text, timestamp } from 'drizzle-orm/pg-core';export const users = pgTable('users', {  id: serial('id').primaryKey(),  email: text('email').notNull().unique(),  name: text('name').notNull(),  createdAt: timestamp('created_at').defaultNow(),});// db/client.tsimport { drizzle } from 'drizzle-orm/node-postgres';import { Pool } from 'pg';import * as schema from './schema';const pool = new Pool({ connectionString: process.env.DATABASE_URL });export const db = drizzle(pool, { schema });

First Query

import { db } from './db/client';import { users } from './db/schema';import { eq } from 'drizzle-orm';// Insertconst newUser = await db.insert(users).values({  email: '[email protected]',  name: 'John Doe',}).returning();// Selectconst allUsers = await db.select().from(users);// Whereconst user = await db.select().from(users).where(eq(users.id, 1));// Updateawait db.update(users).set({ name: 'Jane Doe' }).where(eq(users.id, 1));// Deleteawait db.delete(users).where(eq(users.id, 1));

Schema Definition

Column Types Reference

PostgreSQLMySQLSQLiteTypeScript
serial()serial()integer()number
text()text()text()string
integer()int()integer()number
boolean()boolean()integer()boolean
timestamp()datetime()integer()Date
json()json()text()unknown
uuid()varchar(36)text()string

Common Schema Patterns

import { pgTable, serial, text, varchar, integer, boolean, timestamp, json, unique } from 'drizzle-orm/pg-core';export const users = pgTable('users', {  id: serial('id').primaryKey(),  email: varchar('email', { length: 255 }).notNull().unique(),  passwordHash: varchar('password_hash', { length: 255 }).notNull(),  role: text('role', { enum: ['admin', 'user', 'guest'] }).default('user'),  metadata: json('metadata').$type<{ theme: string; locale: string }>(),  isActive: boolean('is_active').default(true),  createdAt: timestamp('created_at').defaultNow().notNull(),  updatedAt: timestamp('updated_at').defaultNow().notNull(),}, (table) => ({  emailIdx: unique('email_unique_idx').on(table.email),}));// Infer TypeScript typestype User = typeof users.$inferSelect;type NewUser = typeof users.$inferInsert;

Relations

One-to-Many

import { pgTable, serial, text, integer } from 'drizzle-orm/pg-core';import { relations } from 'drizzle-orm';export const authors = pgTable('authors', {  id: serial('id').primaryKey(),  name: text('name').notNull(),});export const posts = pgTable('posts', {  id: serial('id').primaryKey(),  title: text('title').notNull(),  authorId: integer('author_id').notNull().references(() => authors.id),});export const authorsRelations = relations(authors, ({ many }) => ({  posts: many(posts),}));export const postsRelations = relations(posts, ({ one }) => ({  author: one(authors, {    fields: [posts.authorId],    references: [authors.id],  }),}));// Query with relationsconst authorsWithPosts = await db.query.authors.findMany({  with: { posts: true },});

Many-to-Many

export const users = pgTable('users', {  id: serial('id').primaryKey(),  name: text('name').notNull(),});export const groups = pgTable('groups', {  id: serial('id').primaryKey(),  name: text('name').notNull(),});export const usersToGroups = pgTable('users_to_groups', {  userId: integer('user_id').notNull().references(() => users.id),  groupId: integer('group_id').notNull().references(() => groups.id),}, (table) => ({  pk: primaryKey({ columns: [table.userId, table.groupId] }),}));export const usersRelations = relations(users, ({ many }) => ({  groups: many(usersToGroups),}));export const groupsRelations = relations(groups, ({ many }) => ({  users: many(usersToGroups),}));export const usersToGroupsRelations = relations(usersToGroups, ({ one }) => ({  user: one(users, { fields: [usersToGroups.userId], references: [users.id] }),  group: one(groups, { fields: [usersToGroups.groupId], references: [groups.id] }),}));

Queries

Filtering

import { eq, ne, gt, gte, lt, lte, like, ilike, inArray, isNull, isNotNull, and, or, between } from 'drizzle-orm';// Equalityawait db.select().from(users).where(eq(users.email, '[email protected]'));// Comparisonawait db.select().from(users).where(gt(users.id, 10));// Pattern matchingawait db.select().from(users).where(like(users.name, '%John%'));// Multiple conditionsawait db.select().from(users).where(  and(    eq(users.role, 'admin'),    gt(users.createdAt, new Date('2024-01-01'))  ));// IN clauseawait db.select().from(users).where(inArray(users.id, [1, 2, 3]));// NULL checksawait db.select().from(users).where(isNull(users.deletedAt));

Joins

import { eq } from 'drizzle-orm';// Inner joinconst result = await db  .select({    user: users,    post: posts,  })  .from(users)  .innerJoin(posts, eq(users.id, posts.authorId));// Left joinconst result = await db  .select({    user: users,    post: posts,  })  .from(users)  .leftJoin(posts, eq(users.id, posts.authorId));// Multiple joins with aggregationimport { count, sql } from 'drizzle-orm';const result = await db  .select({    authorName: authors.name,    postCount: count(posts.id),  })  .from(authors)  .leftJoin(posts, eq(authors.id, posts.authorId))  .groupBy(authors.id);

Pagination & Sorting

import { desc, asc } from 'drizzle-orm';// Order byawait db.select().from(users).orderBy(desc(users.createdAt));// Limit & offsetawait db.select().from(users).limit(10).offset(20);// Pagination helperfunction paginate(page: number, pageSize: number = 10) {  return db.select().from(users)    .limit(pageSize)    .offset(page * pageSize);}

Transactions

// Auto-rollback on errorawait db.transaction(async (tx) => {  await tx.insert(users).values({ email: '[email protected]', name: 'John' });  await tx.insert(posts).values({ title: 'First Post', authorId: 1 });  // If any query fails, entire transaction rolls back});// Manual controlconst tx = db.transaction(async (tx) => {  const user = await tx.insert(users).values({ ... }).returning();  if (!user) {    tx.rollback();    return;  }  await tx.insert(posts).values({ authorId: user.id });});

Migrations

Drizzle Kit Configuration

// drizzle.config.tsimport type { Config } from 'drizzle-kit';export default {  schema: './db/schema.ts',  out: './drizzle',  dialect: 'postgresql',  dbCredentials: {    url: process.env.DATABASE_URL!,  },} satisfies Config;

Migration Workflow

# Generate migrationnpx drizzle-kit generate# View SQLcat drizzle/0000_migration.sql# Apply migrationnpx drizzle-kit migrate# Introspect existing databasenpx drizzle-kit introspect# Drizzle Studio (database GUI)npx drizzle-kit studio

Example Migration

-- drizzle/0000_initial.sqlCREATE TABLE IF NOT EXISTS "users" (  "id" serial PRIMARY KEY NOT NULL,  "email" varchar(255) NOT NULL,  "name" text NOT NULL,  "created_at" timestamp DEFAULT now() NOT NULL,  CONSTRAINT "users_email_unique" UNIQUE("email"));

Navigation

Detailed References

  • 🏗️ Advanced Schemas - Custom types, composite keys, indexes, constraints, multi-tenant patterns. Load when designing complex database schemas.

  • 🔍 Query Patterns - Subqueries, CTEs, raw SQL, prepared statements, batch operations. Load when optimizing queries or handling complex filtering.

  • ⚡ Performance - Connection pooling, query optimization, N+1 prevention, prepared statements, edge runtime integration. Load when scaling or optimizing database performance.

  • 🔄 vs Prisma - Feature comparison, migration guide, when to choose Drizzle over Prisma. Load when evaluating ORMs or migrating from Prisma.

Red Flags

Stop and reconsider if:

  • Using any or unknown for JSON columns without type annotation
  • Building raw SQL strings without using sql template (SQL injection risk)
  • Not using transactions for multi-step data modifications
  • Fetching all rows without pagination in production queries
  • Missing indexes on foreign keys or frequently queried columns
  • Using select() without specifying columns for large tables

Performance Benefits vs Prisma

MetricDrizzlePrisma
Bundle Size~35KB~230KB
Cold Start~10ms~250ms
Query SpeedBaseline~2-3x slower
Memory~10MB~50MB
Type GenerationRuntime inferenceBuild-time generation

Integration

  • typescript-core: Type-safe schema inference with satisfies
  • nextjs-core: Server Actions, Route Handlers, Middleware integration
  • Database Migration: Safe schema evolution patterns

Related Skills

When using Drizzle, these skills enhance your workflow:

  • prisma: Alternative ORM comparison: Drizzle vs Prisma trade-offs
  • typescript: Advanced TypeScript patterns for type-safe queries
  • nextjs: Drizzle with Next.js Server Actions and API routes
  • sqlalchemy: SQLAlchemy patterns for Python developers learning Drizzle

[Full documentation available in these skills if deployed in your bundle]

drizzle-ormをインストール

スキルファイルをダウンロードし、.claude/skills/ ディレクトリに解凍してください。

ZIPをダウンロード

リポジトリをクローンし、スキルファイルをプロジェクトにコピーしてください。

git clone https://github.com/bobmatnyc/claude-mpm-skills/blob/main/toolchains/typescript/data/drizzle/SKILL.md # Copy SKILL.md to your .claude/skills/ directory

コピー コピー
クイックセットアップ: skillフォルダを.claude/skills/にコピーしてください。Claudeが自動的にそのスキルを検出して使用します。
リポジトリ bobmatnyc/claude-mpm-skills

関連スキル

github-code-search
更新された時間 2026年6月29日
clickhouse-io
更新された時間 2026年6月29日
prisma-client-api
更新された時間 2026年6月29日
coding-standards
更新された時間 2026年6月29日
OR