この記事は約 5 分で読めます。
筆者プロフィール: ソフトウェアエンジニア。「知った気にならない。いつまでも学び続ける」を信条に、業務と個人開発の両輪で技術を磨いています。AI 駆動開発で複数の個人開発アプリを構築・運用中。
👉 ポートフォリオ: 筆者ホームページ
DB マイグレーションは、アプリケーションコードのデプロイと非同期で走る。そのため「新スキーマ × 旧アプリ」「旧スキーマ × 新アプリ」の状態が一時的に発生します。本記事では、運用中の SaaS 「たすきば Knowledge Relay」 で実装している Prisma migration の安全運用を整理します。
サービスの機能紹介・画面イメージ・コンセプトは公式プロダクトページをご覧ください。
👉 たすきば Knowledge Relay — 公式プロダクトページ
Prisma migration の基本フロー
# 1. schema.prisma を編集
vim prisma/schema.prisma
# 2. migration を生成
pnpm prisma migrate dev --name add_user_locale_column
# 3. 生成された SQL を確認
cat prisma/migrations/[timestamp]_add_user_locale_column/migration.sql
# 4. ローカル DB に適用 (3 のコマンドで同時実行)
# 5. PR 作成 → CI で staging に自動適用
# 6. main マージ後、本番に手動適用
シンプルですが、本番反映時に気をつけるポイント があります。
1. 後方互換性を保つマイグレーション
例 1: カラム追加 (safe)
ALTER TABLE users ADD COLUMN locale VARCHAR(10) DEFAULT 'ja';
旧アプリは locale を SELECT しないので問題なし。新アプリは locale を読める。
例 2: カラム削除 (NOT safe in 1 step)
-- ✗ unsafe: 旧アプリが古いカラム参照中にカラム削除 → エラー
ALTER TABLE users DROP COLUMN deprecated_field;
解決 — 2 段階で削除
Step 1: アプリから参照を削除 (deploy)
(コード変更のみ、DB は触らない)
Step 2: アプリのデプロイが完了し、参照が完全になくなったことを確認
Step 3: カラムを物理削除
ALTER TABLE users DROP COLUMN deprecated_field;
2 つの段階を踏むことで、デプロイのタイミングが多少ズレても安全。
2. destructive change のチェックリスト
| 操作 | 注意点 |
|---|---|
| DROP COLUMN | 2 段階で進める |
| DROP TABLE | データ消失リスク、事前バックアップ必須 |
| RENAME COLUMN | 旧名 + 新名の同時存在 → 旧名削除の 2 段階 |
| ALTER TYPE (型変更) | データ変換不可な場合あり、慎重に |
| NOT NULL 制約追加 | 既存データに値を埋めてから |
destructive change は「1 度きりの操作」なので、必ず事前検証 + バックアップ。
3. NULL を許容する設計
新規カラムは、基本的に NULL を許容 (DEFAULT 値も設定)。
model User {
locale String? @default("ja") // NULL 許容 + デフォルト
}
| 効果 | 内容 |
|---|---|
| 既存 row に DEFAULT 値 |
ALTER COLUMN で自動付与 |
| アプリの後方互換性 | locale が NULL でも対応可能 |
既存データを壊さず、後方互換性を保つ。
4. ローカル / staging / 本番の 3 段階
[Local DB]
↓ pnpm prisma migrate dev でテスト
[Staging Supabase]
↓ PR 作成時に CI が自動 migrate deploy
[Production Supabase]
↓ main マージ後、手動 migrate deploy
3 段階のうち、本番だけが手動。
| 理由 | 内容 |
|---|---|
| 自動 migration のリスク | 事故時のリスクが大きすぎる |
| 段階的反映 | 各環境で検証してから次へ |
5. マイグレーション失敗時の対応
万一、本番 migration が失敗したら:
# 失敗した migration を確認
pnpm prisma migrate status
# 状況確認 + 修復
# (手動 SQL で状態を直す)
# 修復後、マイグレーション履歴を resolve
pnpm prisma migrate resolve --applied [migration_name]
Prisma は migration 失敗時の状態を _prisma_migrations テーブルに記録。ここを手動で操作することで状況を制御 できます。
ただし、これは 最終手段。基本は事前検証で防ぎます。
6. ロールバック戦略
Prisma の migration には自動ロールバック機能がありません。そのため、ロールバックは:
新しい migration を追加して、変更を巻き戻す
-- 元の migration: locale カラム追加
ALTER TABLE users ADD COLUMN locale VARCHAR(10);
-- ロールバック migration: 削除する
ALTER TABLE users DROP COLUMN locale;
「戻す」ではなく「前に進めて打ち消す」発想。
| 効果 | 内容 |
|---|---|
| migration 履歴が保持される | 削除しない |
| ロールバック時期が追跡可能 | どの migration で戻したか |
| 全環境で同じシーケンスを再現 | 履歴の整合性 |
7. 本番直前 backup の運用
destructive migration を本番で実行する前に、必ず DB backup を取ります。
# Supabase の管理画面から手動バックアップ作成
# または pg_dump で直接バックアップ
pg_dump -h xxx.supabase.co -U postgres -d postgres > backup-YYYYMMDD.sql
backup を取った後にマイグレーション実行。万一の事故時に、backup から復元できる状態を保ちます。
8. Schema drift の検知
Prisma schema と実 DB の状態が乖離する (schema drift) と、後の migration がエラーになります。
pnpm prisma migrate status
| 検知できること | 内容 |
|---|---|
| 未適用の migration リスト | どれを反映していないか |
| schema drift | DB に存在するが Prisma schema にないもの |
drift があれば、修正してから次の migration へ。特に、手動 SQL で本番を操作した場合は drift が発生しがち。
9. migration コミットのルール
□ 1 PR で 1〜数本の migration
□ 命名は migration.sql (Prisma 標準)
□ ファイル名にタイムスタンプ + 説明
PR レビュー時:
□ generated migration SQL を必ず人間が確認
□ 想定外の DROP / RENAME が混入していないか
□ destructive change の場合は専用 PR
おわりに
| 仕組み | 効果 |
|---|---|
| 後方互換性を保つ migration | アプリ / DB 同期ズレに耐性 |
| destructive change は 2 段階 | データ消失リスク回避 |
| ローカル / staging / 本番 の 3 段階反映 | 事故防止 |
| 本番直前 backup | 復元可能 |
| schema drift 検知 | 履歴の整合性 |
| ロールバックは新 migration で前進 | 履歴保持 |
DB migration は地味だが、長期運用の信頼性を支える根幹。事前検証 + 後方互換性の意識で、安定運用できます。
本記事の migration 運用は、運用中の SaaS 「たすきば Knowledge Relay」 で実装しています。
👉 たすきば Knowledge Relay — 公式プロダクトページ