Next.js × ORM 実践比較:Prisma / Drizzle / Kysely をDocker上で動かして違いを体感する【後編】
はじめに
前編では、Next.js App Router 環境におけるORM選定の観点として、型安全性、マイグレーション、Edge対応、マネージドDBとの相性などを軸に、Prisma / Drizzle ORM / Kysely の3つのORMを比較しました。
👉 前編はこちら:
この記事(後編)では、それぞれのORMを実際に導入・実装して比較していきます。
本記事の方針:実際に動かして体感する
Docker上にPostgreSQLとMySQLの両方を構築
各ORMごとにマイグレーション定義・テーブル作成・API実装までを一通り行う
同じ「ユーザー一覧取得API」をそれぞれのORMで書いて比較
実装のしやすさや運用のクセ、型まわりの手触りを実践ベースで体感
この記事で得られること
- 「Prismaって便利だけど重いって言われる理由は?」
- 「Drizzleって最近聞くけど、本当に扱いやすい?」
- 「Kyselyの型推論って実際どう?」
といった、使ってみなければ分からない実装レベルの違い・思想の違いを、自分の手で試しながら理解できる構成になっています。
対象環境・前提
- Next.js 14(App Router構成)
- 各ORMはAPI Route(app/api/users/route.ts)で利用
- DockerでPostgreSQL / MySQLをローカルに立ち上げて接続
- フロントUIやSWRなどは扱わず、API層の比較に集中
前提知識として推奨
- Next.js App Routerの構造に触れたことがある
- ORMを1つでも使ったことがある(Prismaなど)
- Dockerの基本的な使い方(
docker-compose up
できる程度)
それでは、まずは環境構築からはじめていきましょう。
次章では、PostgreSQLとMySQLを同時に扱えるDocker構成を用意し、.envを共通化していきます。
今回実装したコードはこちらのリポジトリに格納してありますので合わせてご参照ください。
環境構築(共通準備)
Next.jsプロジェクトの作成とPostgreSQLとMySQLを扱えるDockerコンテナの起動から始めます。
1. プロジェクト作成(orm-app/ ディレクトリ)
npx create-next-app@latest orm-app \
--ts \
--app \
--tailwind \
--eslint \
--src-dir \
--import-alias "@/*"
プロジェクトが作成できましたら開発モードで起動できることを確認します。
npm run dev
2. docker-compose.ymlの作成
Dockerで以下2つのDBを立ち上げます。
- PostgreSQL(Prisma / Drizzle向け)
- MySQL(Kysely向け)
version: '3.9'
services:
postgres:
image: postgres:15
restart: always
environment:
POSTGRES_USER: user
POSTGRES_PASSWORD: password
POSTGRES_DB: appdb
ports:
- '5432:5432'
volumes:
- pgdata:/var/lib/postgresql/data
mysql:
image: mysql:8
restart: always
environment:
MYSQL_ROOT_PASSWORD: password
MYSQL_DATABASE: appdb
MYSQL_USER: user
MYSQL_PASSWORD: password
ports:
- '3306:3306'
volumes:
- mysqldata:/var/lib/mysql
volumes:
pgdata:
mysqldata:
yamlファイルを作成したらDockerを起動します。
docker-compose up -d
Dockerコンテナ内で接続確認を行います。
PostgreSQL編
コンテナに接続
docker exec -it <postgresコンテナ名> bash
psqlコマンドで接続
psql -U user -d appdb
MySQL編
コンテナに接続
docker exec -it <mysqlコンテナ名> bash
mysqlコマンドで接続
mysql -u user -p
- パスワード:
password
.env.local
の作成
DB接続用 # PostgreSQL for Prisma / Drizzle
POSTGRES_URL=postgresql://user:password@localhost:5432/appdb
# MySQL for Kysely
MYSQL_URL=mysql://user:password@localhost:3306/appdb
ディレクトリ構成の確認
いくつかファイルを作成しましたので念のため現在のディレクトリ構成を記載しておきます。
tree -I node_modules -I .git -I public -I .next --dirsfirst -a
.
├── src
│ └── app
│ ├── favicon.ico
│ ├── globals.css
│ ├── layout.tsx
│ └── page.tsx
├── .env.local
├── .gitignore
├── README.md
├── docker-compose.yml
├── eslint.config.mjs
├── next-env.d.ts
├── next.config.ts
├── package-lock.json
├── package.json
├── postcss.config.mjs
└── tsconfig.json
📁 src/app/
これは Next.js App Router 専用のルーティングディレクトリです。以下のような構成が基本になります:
ファイル・フォルダ | 役割 |
---|---|
page.tsx |
トップページ (/ ) に対応するルートコンポーネント |
layout.tsx |
ページ全体の共通レイアウト(HTML構造や共通スタイルなど) |
globals.css |
全体で使うグローバルCSS(Tailwind等と併用されやすい) |
favicon.ico |
ブラウザのタブに表示されるアイコン |
📄 .env.local
環境変数をローカル開発用に記述するファイル(例:DATABASE_URL=...)。
Gitに含めず、個人ごとの設定を保持する目的で使います。
📄 docker-compose.yml
複数のDockerコンテナ(DBやアプリ)を同時に立ち上げるための設定。
例えば、MySQLやPostgreSQLなどの開発用DBを構成している可能性があります。
📄 eslint.config.mjs
ESLint(静的解析ツール)の設定ファイル(ESM形式)。
コードの品質・構文ルールを統一するために使用されます。
📄 next-env.d.ts
Next.js によって自動生成される型定義ファイル。
TypeScript が next 環境を正しく認識できるようにするための補助。
📄 next.config.ts
Next.js のビルド設定ファイル(TypeScript形式)。
例:画像ドメイン許可、リダイレクト、モジュールエイリアスなどの指定が可能。
📄 package.json & package-lock.json
ファイル | 内容 |
---|---|
package.json |
プロジェクトの依存ライブラリ、スクリプト、メタ情報を記述 |
package-lock.json |
実際にインストールされたパッケージのバージョンを固定・記録(再現性の保証) |
📄 postcss.config.mjs
PostCSS の設定ファイル。
Tailwind CSS を使っている場合、ここでプラグイン指定を行います。
📄 tsconfig.json
TypeScript のコンパイラ設定。
パスエイリアス(@/ など)や strict モード、モジュール形式などをここで制御します。
Prisma編:マイグレーションと API 実装(PostgreSQL)
このセクションでは、Prisma を使って Next.js App Router 環境におけるユーザーデータの読み取り API を構築します。Docker 上の PostgreSQL に接続し、マイグレーション・データ登録・API 実装・型安全な開発体験までを一通り確認します。
Prisma のセットアップ
依存パッケージのインストールと初期化
npm install prisma @prisma/client
npx prisma init
生成される構成:
prisma/
└── schema.prisma
.env
接続設定
.env.local
と.env
に以下を記載します。
POSTGRES_URL=postgresql://user:password@localhost:5432/appdb
Prisma スキーマ定義
prisma/schema.prisma
を以下のように定義します:
generator client {
provider = "prisma-client-js"
}
datasource db {
provider = "postgresql"
url = env("POSTGRES_URL")
}
model User {
id Int @id @default(autoincrement())
name String
email String @unique
}
マイグレーションの実行
npx prisma migrate dev --name init
テーブルが作成されました。
下記コマンドで確認できます。
npx prisma studio
先ほど指定したカラムが存在していますが、レコードはまだありません。
初期データ投入(seed)
prisma/seed.ts
を作成:
const { PrismaClient } = require('@prisma/client')
const prisma = new PrismaClient()
async function main() {
await prisma.user.createMany({
data: [
{ name: 'Alice', email: 'alice@example.com' },
{ name: 'Bob', email: 'bob@example.com' },
{ name: 'Charlie', email: 'charlie@example.com' },
],
})
await prisma.$disconnect()
}
main().catch((e) => {
console.error(e)
process.exit(1)
})
実行準備
npm install -D ts-node
実行
npx ts-node prisma/seed.ts
レコードが3件作成されたことが確認できます。
API の実装
src/lib/prisma.ts
import { PrismaClient } from '@prisma/client'
const globalForPrisma = globalThis as unknown as {
prisma: PrismaClient | undefined
}
export const prisma = globalForPrisma.prisma ?? new PrismaClient()
if (process.env.NODE_ENV !== 'production') globalForPrisma.prisma = prisma
- なぜこのような書き方をしているのか?
Next.js(特にApp Router)では、開発中にモジュールが ホットリロード(HMR)されるたびに再実行されることがあります。
そのたびにnew PrismaClient()
を呼んでしまうと、Prismaの接続数制限(特にPlanetScaleやSupabaseなどのマネージドDB)を超えてしまい、接続エラーになります。
行 | 意味と狙い |
---|---|
globalThis の利用 |
グローバル変数として prisma インスタンスを保持し、使い回せるようにする |
globalForPrisma.prisma ?? new PrismaClient() |
初回実行時は新しく作り、それ以降は再利用する |
if (process.env.NODE_ENV !== 'production') |
本番環境では毎回生成しても問題ない(1プロセス前提)ため、グローバル汚染を避ける |
このパターンはよく「Singletonパターン(開発環境用)」として使われます。
src/app/api/prisma/users/route.ts
import { prisma } from '@/lib/prisma'
export async function GET() {
const users = await prisma.user.findMany()
return Response.json(users)
}
解説
app/api/prisma/users/route.ts
は Next.js App Router の API ルート- このファイルがあることで
GET /api/prisma/users
というエンドポイントが自動的に生成される
- このファイルがあることで
prisma.user.findMany()
は User モデルの全レコードを取得するメソッド- 戻り値は
User[]
型(Prismaが自動生成)
- 戻り値は
Prisma + App Router のAPIの魅力
ポイント | 内容 |
---|---|
1ファイルで完結 | route.ts だけでAPIエンドポイントを完結できる |
型安全 | prisma.user.findMany() の引数・戻り値に型が付く |
再利用性が高い | Prisma Clientは使いまわしやすく、複数APIで共有できる |
null・undefined防止 | Prismaの戻り値は適切なUnion型 |
確認:
http://localhost:3000/api/prisma/users
先ほど作成したユーザーがレスポンスとしてされていればOKです。
型安全な開発体験の具体例
await prisma.user.findMany()
の戻り値の型が明示されています。
// 特定のユーザー取得例
const user = await prisma.user.findUnique({
where: { id: 1 },
})
// 型エラー例(存在しないフィールドを渡すとエラー)
await prisma.user.findUnique({
where: { foo: 123 } // ❌ 型エラー
})
エディター上でもfoo
が存在しないことを確認できます。
データ削除(後片付け)
コンテナに接続し、DBに接続した後に、下記コマンドを実行します。
DROP SCHEMA public CASCADE;
CREATE SCHEMA public;
解説
コマンド | 意味 |
---|---|
DROP SCHEMA public CASCADE; |
publicスキーマ(≒全テーブル)を削除 |
CREATE SCHEMA public; |
空のスキーマを再作成 |
このように Prisma は、型の信頼性と記述の簡潔さを両立しつつ、高速な開発体験を提供してくれます。
次章では、SQLライクで軽量な構文が特徴の Drizzle ORM を使って、同じ処理を実装して比較してみます。
Drizzle ORM編:マイグレーションと API 実装(PostgreSQL)
このセクションでは、Drizzle ORM を使って Next.js App Router 環境におけるユーザーデータの読み取り API を構築します。Prismaと同様に Docker 上の PostgreSQL に接続し、スキーマ定義・マイグレーション・初期データ投入・API 実装までを順に確認していきます。
Drizzle のセットアップ
依存パッケージのインストール
npm install drizzle-orm pg postgres
npm install -D drizzle-kit @types/pg
drizzle-orm
: ORM 本体
pg
,postgres
: PostgreSQL ドライバ
drizzle-kit
: CLI ツール(マイグレーション用)
drizzle.config.ts の作成
プロジェクトルートに drizzle.config.ts
を作成:
import { defineConfig } from 'drizzle-kit'
export default defineConfig({
dialect: "postgresql",
schema: './src/schema/drizzle-schema.ts',
out: './drizzle',
dbCredentials: {
url: process.env.POSTGRES_URL as string,
},
})
項目 | 内容 |
---|---|
DBの種類 | PostgreSQL を使用する |
スキーマ定義 | TypeScriptファイル(pgTable() )で行う |
マイグレーション生成先 | ./drizzle ディレクトリ |
接続情報 | POSTGRES_URL 環境変数で指定された接続文字列を使う |
3. スキーマ定義
Drizzle ORM では、テーブル定義そのものを TypeScript ファイル上で行います。これにより、スキーマ定義と型情報が一致し、IDE 補完や型チェックによる安心感が得られます。
src/schema/drizzle-schema.ts
を作成:
import { pgTable, serial, varchar } from 'drizzle-orm/pg-core'
export const users = pgTable('users', {
id: serial('id').primaryKey(),
name: varchar('name', { length: 255 }).notNull(),
email: varchar('email', { length: 255 }).notNull().unique(),
})
💡 解説:
pgTable()
は PostgreSQL 用のテーブル定義関数で、1つ目の引数がテーブル名、2つ目がカラム定義のオブジェクトです。serial()
は PostgreSQL のSERIAL
型に対応。自動インクリメントする主キーです。varchar()
は可変長文字列型。{ length: 255 }
のように長さを明示します。.notNull()
を付けるとNOT NULL
制約を加えます。.unique()
を付けるとユニークインデックスが張られます。
Drizzle ではこのように TypeScript の文法でスキーマ定義ができるため、別途 Prisma のような DSL ファイルを定義する必要がなく、スキーマとコードの乖離が起きにくいのが大きな利点です。
マイグレーションの実行
初期化(最初のみ)
npx drizzle-kit generate
DBに適用
npx drizzle-kit push
Drizzle Studioで確認
Prismaと同様にGUIでテーブルを確認できます。
npx drizzle-kit studio
コンソールに表示されたURLにアクセスするとusers
テーブルが作成されていることが確認できます。
初期データ投入(seed)
prisma/seed.ts
と同様に、scripts/drizzle-seed.ts
を作成:
import { drizzle } from 'drizzle-orm/node-postgres'
import { users } from '@/schema/drizzle-schema'
import { Client } from 'pg'
import 'dotenv/config'
const client = new Client({ connectionString: process.env.POSTGRES_URL })
await client.connect()
const db = drizzle(client)
await db.insert(users).values([
{ name: 'Alice', email: 'alice@example.com' },
{ name: 'Bob', email: 'bob@example.com' },
{ name: 'Charlie', email: 'charlie@example.com' },
])
await client.end()
依存パッケージのインストール
npm i dotenv
npm i -D tsx
実行方法
npx tsx scripts/drizzle-seed.ts
Drizzle Studioでレコードが3件作成されていることを確認します。
API の実装
このセクションでは、Drizzle ORM を使って /api/drizzle/users
という API エンドポイントを作成します。Next.js の App Router における API Route の仕組みと、Drizzle のクエリ構築方法を理解する上で重要な実装パートです。
src/lib/drizzle.ts
import { drizzle } from 'drizzle-orm/node-postgres'
import { Client } from 'pg'
const client = new Client({ connectionString: process.env.POSTGRES_URL })
client.connect()
export const db = drizzle(client)
💡 解説:
pg
パッケージのClient
を使って PostgreSQL に接続しています。drizzle(client)
によって型安全なクエリビルダーが生成され、db
経由であらゆる操作が可能になります。- 接続は一度だけ行い、アプリ内で使いまわす設計です(グローバルキャッシュを導入してもよい)。
src/app/api/drizzle/users/route.ts
import { db } from '@/lib/drizzle'
import { users } from '@/schema/drizzle-schema'
export async function GET() {
const result = await db.select().from(users)
return Response.json(result)
}
解説:
-
Next.js App Router では
route.ts
を配置するだけで API エンドポイントが自動的に生成されます。- この場合、
/api/drizzle/users
が生成されます。
- この場合、
-
db.select().from(users)
という記述は Drizzle の SQL DSL(Domain Specific Language)構文で、users
はpgTable()
で定義された型付きテーブル.select()
で全カラムを、.from()
で対象テーブルを指定
-
Response.json(result)
により、取得したデータをそのままJSONで返しています。 -
戻り値の型は
typeof users._.columns
に基づいて推論され、型安全性が保たれます。
確認:
http://localhost:3000/api/drizzle/users
3件のレコードがレスポンスに含まれていることが確認できます。
型安全な開発体験の具体例
Prisma同様、db.select().from(users)
の戻り値の型が明示されています。
const result = await db.select().from(users).where(eq(users.id, 1))
// 型エラー例:存在しないカラム名を指定するとエラー
await db.select({ foo: users.foo }).from(users) // ❌ コンパイルエラー
データ削除(後片付け)
DROP SCHEMA public CASCADE;
CREATE SCHEMA public;
Drizzle ORM は、SQLライクな構文と静的型付けのバランスがよく、App Router + Edge Runtime を見据えた構成にも適しています。次は Kysely を用いた比較実装に進んでいきます。
Kysely編:App Router × Kysely(MySQL)
このセクションでは、Kysely を使って Next.js App Router 環境におけるユーザーデータの取得APIを構築します。Prisma や Drizzle に比べて "よりSQLライクに" 書ける構文と、型の推論力に定評があるのが特徴です。MySQL(PlanetScale なども視野)を接続先とし、マイグレーション・データ登録・API 実装の流れを確認します。
Kysely のセットアップ
パッケージのインストール
npm i kysely mysql2
型定義ファイルの作成
Kyselyでは、テーブルごとの型を自分で定義して渡す必要があります。
import { Generated } from "kysely"
export interface UserTable {
id: Generated<number>
name: string
email: string
}
export interface Database {
users: UserTable
}
Generated<T>
とは?INSERT
時には省略可能SELECT
時には存在する値として扱われる
Kysely クライアントの初期化
import { Kysely, MysqlDialect } from 'kysely'
import { createPool } from 'mysql2'
import type { Database } from '@/types/db'
const dialect = new MysqlDialect({
pool: createPool({
database: 'appdb',
user: 'user',
password: 'password',
host: 'localhost',
port: 3306,
})
})
export const db = new Kysely<Database>({ dialect })
マイグレーション(手動で SQL 実行)
Kysely は Prisma や Drizzle のようにマイグレーションの仕組みを持っていますがやや使いにくいです。
そのため、スキーマの管理は手動で SQL を実行する方法を今回は採用しました。
以下は users
テーブルを作成するための SQL です:
CREATE TABLE users (
id INT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(255) NOT NULL,
email VARCHAR(255) NOT NULL UNIQUE
);
この SQL を実行するには、Docker 上で起動している MySQL コンテナに入って実行するのが一般的です。以下のようにして操作できます:
# コンテナに入る
docker exec -it orm-comparison_mysql_1 bash
# MySQLシェルにログイン
mysql -u user -p
# パスワード: password
# DBを選択
USE appdb;
# 上記の CREATE TABLE 文を実行
この手動マイグレーションはやや手間ですが、その分 SQL による明示的な制御が可能で、PlanetScale のようにスキーマ変更に制約があるサービスとの相性も良好です。
PlanetScaleやDockerのMySQLに入って直接実行するか、初期化スクリプトとして用意します。
初期データ投入(seed)
import 'dotenv/config'
import { db } from '@/lib/kysely'
async function main() {
await db.insertInto('users').values([
{ name: 'Alice', email: 'alice@example.com' },
{ name: 'Bob', email: 'bob@example.com' },
{ name: 'Charlie', email: 'charlie@example.com' },
]).execute()
await db.destroy()
}
main().catch((e) => {
console.error(e)
process.exit(1)
}).finally(() => {
process.exit(0)
})
実行方法:
npx tsx scripts/kysely-seed.ts
APIの実装(初期データ投入後に確認)
初期データの投入が完了したら、次のように API エンドポイントを実装してデータ取得の動作を確認できます。
Next.js App Router では、app/api
以下に配置した route.ts
ファイルによって API エンドポイントが自動的に生成されます。この例では、/api/kysely/users
が GET リクエストに対応するようになります。
また、Kysely のクエリ構文は SQL の構造に似ており、.selectFrom('users').selectAll()
で SELECT * FROM users
に相当するクエリを構築できます。
import { db } from '@/lib/kysely'
export async function GET() {
const users = await db.selectFrom('users').selectAll().execute()
return Response.json(users)
}
http://localhost:3000/api/kysely/users
このエンドポイントにアクセスすることで、先ほど seed で投入した Alice
, Bob
, Charlie
のデータが JSON 形式で返ってくるはずです。
idが4〜6になっているのはデータを再作成した影響ですので特に気にする必要はありません。
型安全な開発体験
存在しないテーブルを指定すると警告が表示されます。
const result = await db
.selectFrom('users')
.select(['id', 'name'])
.where('email', '=', 'alice@example.com')
.execute()
- テーブル名、カラム名はリテラル文字列ではなく補完・型チェック対象になる
selectFrom().select()
の時点でカラムの型も推論される- 誤字や存在しないカラムを指定するとビルドエラーになる
存在しないカラムを指定してwhere句を作成しても警告が表示されます。
戻り値も認識されておりコード上の扱いも問題ありません。
Kysely は SQL に近い記述で柔軟に書きたい人に最適で、PlanetScale(MySQLベース)との相性も良好です。特に型推論の正確さは非常に高く、スキーマとコードの乖離を最小限に保ちつつ開発できます。
以上で、Prisma / Drizzle / Kysely のそれぞれについて、App Router 環境での使い方と使い心地を確認しました。次回はこれらを踏まえて、どのORMがどのユースケースに合うのかを総括します。
コードの比較まとめ
ORM | 実装の書きやすさ | マイグレーション | 型安全 | Edge対応 | 接続初期化のしやすさ |
---|---|---|---|---|---|
Prisma | ◎ | ◎ | ◎ | △ | ◎ |
Drizzle | ◎ | ○ | ◎ | ◎ | ◎ |
Kysely | ○ | △ | ◎ | ◎ | ○ |
おわりに
実装してみて初めて見える「思想の違い」
今回、Prisma・Drizzle・Kysely の3つのORMを Next.js App Router 上で実装・比較してきました。それぞれ一見「似たようなことができる」ように見えて、実際に触ってみると設計思想や開発体験に大きな違いがあることがよく分かります。
たとえば、Prismaは「型安全を軸に据えた包括的なORM体験」、Drizzleは「マイグレーションも含めてTypeScriptで完結する一貫性」、Kyselyは「SQLとの距離を極力保ちながら型の恩恵を得る」アプローチです。
ORMは「どれが優れているか」ではなく「どう使いたいか」で選ぶべき
ここまで比較してきた通り、ORM選定で重要なのは「機能の多さ」や「速度」ではなく、「どんな思想で開発したいか」「チームのスキルセットに合っているか」です。
- Prisma の抽象化は、複雑なJOINや細かいクエリよりも「開発速度」と「型安全性」を重視したい人に向いています。
- Drizzle は、シンプルで軽く、かつ TypeScript だけで完結させたいというニーズに強く応えます。
- Kysely は、SQLとの距離を保ちながらも型を最大限に活かしたいエンジニア向きです。
それぞれのORMが得意な構成/不得意なユースケース
ORM | 得意なケース | 苦手なケース |
---|---|---|
Prisma | 型安全で高速に開発したいアプリケーション | SQLを細かく制御したい/PlanetScale利用時 |
Drizzle | 軽量・直感的・TSベースで構成したいモダン構成 | 高度なリレーションや抽象化が必要な場合 |
Kysely | SQLとの近さを保ちつつ型の恩恵を最大限に得たい | マイグレーションを自動管理したい場合 |
Next.js App Router の構造は、かつての Pages Router と比べて「APIもコンポーネントも関数単位」で完結する方向に進化しています。その中で、どのORMが自然に組み込めるか、どのように構成するのが開発チームにとって無理がないかを見極めることが、選定のポイントになります。
最終的には、「何を実現したいか」と「どんなコードが書きたいか」に立ち返って選ぶことが、健全な技術選定につながると感じました。
今回実装したコードはこちらのリポジトリに格納してありますので合わせてご参照ください。
Supabase / PlanetScaleで試す際の追加ポイント(接続・制限・設定)
Supabase / PlanetScale で試す際の追加ポイント(接続・制限・設定)
今回の比較ではローカルの Docker 上に立てた DB を対象に検証しましたが、実際のプロジェクトでは Supabase や PlanetScale などのマネージドデータベースを使うケースも多くなってきました。
ここでは、それらのサービス上で ORM を試す際に押さえておきたい接続方法や制限、設定上の注意点を補足します。
Supabase(PostgreSQL)の場合
- 接続URLの形式
SupabaseのダッシュボードからDatabase > Connection Pooling
もしくはConnection string
を選び、.env.local
に以下のように記述します
POSTGRES_URL=postgresql://postgres:your-password@db.xxxx.supabase.co:5432/postgres
-
SSLが必須
Supabaseの接続はSSLがデフォルトで有効です。ORMによっては、接続オプションにssl: { rejectUnauthorized: false }
を明示する必要があります(Kysely / TypeORM など)。 -
リモート接続の許可
プロジェクト作成直後は一部IPからの接続が制限されていることがあるため、必要に応じて Supabase 側の設定で「外部接続を許可」するオプションを確認してください。
PlanetScale(MySQL)の場合
-
接続先は「ブランチ」単位
PlanetScale では「production」「development」などのブランチ単位で接続URLが異なります。接続用のパスワードも個別に生成する必要があります。 -
DATABASE_URL
に直接使えない問題(Prisma)
PlanetScale は標準の MySQL 機能のうちいくつか(例:外部キー制約、複雑なDDL)をサポートしていません。Prismaで使う際は.env
に次のように書き、schema.prisma
側でreferentialIntegrity = "prisma"
にする必要があります。
DATABASE_URL=mysql://<username>:<password>@<host>/<db>?sslaccept=strict
-
Edge対応ライブラリあり
PlanetScale は@planetscale/database
ライブラリを提供しており、これを使えば Next.js Edge Runtime や Cloudflare Workers などfetch
ベースの環境でも MySQL に接続可能です(Prisma / TypeORM は非対応)。 -
マイグレーションの制約
PlanetScale は「オンラインスキーマ変更」を前提としたワークフロー(GUI/CLI)を採用しており、ORMが直接マイグレーションを流す設計とは相性が悪いことがあります。Drizzle や Kysely のようにマイグレーションを明示的に管理・分離できる構成が好まれます。
このように、Supabase / PlanetScale を本番や検証で使う場合、ORM側の設定だけでなくサービス固有の制約や挙動を正しく理解しておくことが重要です。「ORMが対応しているか」だけではなく、「そのORMがそのDBの制限にどう向き合っているか」に注目することで、よりトラブルの少ない構成選びができるはずです。
関連する技術ブログ
チャットアプリ(画像・PDF送信、ビデオ通話機能付き)
お客様固有の要件を除き一般的なチャットアプリに求められる最低限の機能を実装しデモアプリとしてご紹介いたします。
shinagawa-web.com
管理ダッシュボード機能(グラフ表示、データ取り込み)
一般的な家計簿アプリとして求められる最低限の機能を実装しデモアプリとしてご紹介いたします。
shinagawa-web.com
NestJSで記事投稿APIを作ろう ─ Prisma導入とCRUD実装の基本
NestJSとPrismaを使って、シンプルな記事投稿APIを一から作っていく手順をまとめました。開発環境の整え方から、データベースとの接続、APIの作成、データのチェック(バリデーション)まで、基本を一歩ずつ丁寧に解説しています。
shinagawa-web.com
NestJSアプリの信頼性を高める ─ ログ・エラーハンドリング・テスト戦略
NestJSアプリを本番品質へと近づけるために、ロギング・例外処理の共通化・ユニットテストとE2Eテストの構築までを丁寧に解説。実践的なコードと構成例を通じて、信頼されるAPI設計の基礎を整えます。
shinagawa-web.com
NestJS × Prismaで深めるDB設計 ─ モデル・リレーション・運用設計
NestJSとPrismaを組み合わせ、実践的なデータベース設計・リレーション定義・マイグレーション運用の基本を整理します。単なるAPI開発に留まらず、運用を見据えた設計力を着実に積み上げ、次回のフロントエンド連携へとつなげます。
shinagawa-web.com
NestJS × React × Railway:ブログUIを実装して本番環境へデプロイ
NestJS+React+Prismaで構成したブログアプリを、Dockerで本番ビルドし、クラウドサービス「Railway」へデプロイするまでの手順をまとめました。本番DB接続、環境変数管理、フロントエンドとバックエンドの統合配信など、運用を意識した実践的な構成に仕上げていきます。個人開発やPoCにも応用できる「即戦力の本番構成」を一緒に組み立てていきましょう。
shinagawa-web.com
Next.jsとAuth.jsで認証機能を実装するチュートリアル
Next.jsでアプリケーションを作る時に必要となる認証機能をどのように実装するかをご紹介する記事となります。アカウント登録から始まり、ログイン、ログアウト、ページごとのアクセス制御、OAuth、二要素認証、パスワードリセットなど認証に関連する様々な機能をコードベースでご紹介します。
shinagawa-web.com
Next.js App Routerに最適なORMを徹底比較:Prisma / Drizzle / Kysely / TypeORMの選び方ガイド【前編】
Next.jsのApp Router構成でデータベースと接続する際、どのORMを選ぶべきか?Prisma・Drizzle ORM・Kysely・TypeORMの4つを比較し、型安全性やマイグレーション、Edge対応、Supabase / PlanetScale との相性など、App Routerに適したORM選定の観点を整理します。
shinagawa-web.com
弊社の技術支援サービス
無駄なコストを削減し、投資対効果を最大化する
クラウド費用の高騰、不要なSaaSの乱立、開発工数の増加――これらの課題に悩んでいませんか?本サービスでは、クラウドコストの最適化、開発効率向上、技術選定の最適化 を通じて、単なるコスト削減ではなく、ROIを最大化する最適解 をご提案します。
shinagawa-web.com
最新技術の導入・検証を支援するPoCサービス
Remix、React Server Components、TypeScript移行、クラウドサービス比較、マイクロサービス、サーバーレス、デザインシステムなど、最新技術のPoC(概念実証)を通じて、最適な技術選定と導入を支援します。貴社の開発課題に合わせた検証・実装で、ビジネスの成長を加速させます。
shinagawa-web.com
開発生産性を最大化するための技術支援
開発チームの生産性向上、コードの品質管理、インフラの最適化まで、様々な側面からサポートします。コードベースのリファクタリングから、テスト自動化、オンボーディング強化まで、プロジェクトの成功に必要なすべての支援を提供。御社の開発現場が効率的に機能するように、技術的な障害を取り除き、スムーズな開発を実現します。
shinagawa-web.com
開発品質向上支援 – 効率的で安定したプロダクトを実現
フロントエンドからバックエンド、データベースまで、開発プロセス全体を最適化し、安定したプロダクト作りをサポートします。コードレビューの仕組み、型定義の強化、E2Eテスト環境の構築など、開発の各ステップにおけるベストプラクティスを導入することで、より効率的でバグの少ない、そしてユーザー満足度の高いサービス提供を支援します。
shinagawa-web.com
Webアプリのセキュリティ強化支援
Webアプリの脆弱性対策からインフラのセキュリティ強化まで、包括的なセキュリティ支援を提供。OWASP Top 10対策、JWT認証の最適化、APIのアクセス制御、依存パッケージの監査、セキュアコーディングの標準化など、実践的なアプローチで開発現場の安全性を向上させます。
shinagawa-web.com
目次
お問い合わせ