🛡️

DBマイグレーション運用術:開発・本番環境を安全に管理する方法

2 か月前
2

この記事は、ひとりでつくるSaaS - 設計・実装・運用の記録 Advent Calendar 2025 の8日目の記事です。

昨日の記事では「データベースのID設計」について書きました。この記事では、DBマイグレーションの運用方法について解説します。

:::message
この記事で紹介する方法は、試行錯誤の末にたどり着いた独自のやり方です。もっと良い方法があれば、ぜひコメントで教えてください。
:::

🎯 一般的なマイグレーション管理の方法

DBマイグレーションには、いくつかの管理方法があります。

ORMのマイグレーション機能を使う

Drizzle ORM、Prisma、TypeORMなどのORMには、マイグレーション機能が組み込まれています。

# Drizzle ORMの場合 npx drizzle-kit generate # スキーマからマイグレーションを生成 npx drizzle-kit migrate # マイグレーションを適用

たとえば、TypeScriptでテーブル定義を書くと、その変更を検出して ALTER TABLE などのSQLを自動生成してくれます。

メリット:

  • コードの変更から自動でマイグレーションSQLを生成
  • 適用履歴をDBのテーブルで管理
  • コマンド一発で適用できる

課題:

  • 複雑なデータ移行(既存データの変換など)には対応しにくい
  • 何が実行されるか把握しづらいことがある

複数環境を管理する場合の課題

ORMのマイグレーション機能は単一環境の管理には便利ですが、開発環境と本番環境を分けて運用する場合、以下のような課題があります。

  • 開発環境と本番環境でスキーマが合わなくなる
  • 「開発で適用したが本番にはまだ」という状態が把握しづらい
  • 何をいつ適用したか分からなくなる

私が開発しているMemoreruでも同じ課題に直面し、試行錯誤の結果、現在のような運用ルールにたどり着きました。

📂 個人開発プロダクトでのマイグレーション管理

連番ファイルで時系列管理

マイグレーションファイルはClaude Codeに作成してもらい、連番で管理しています。

database/migrations/ ├── sql/ │ ├── 001_create_users_table.sql │ ├── 002_create_posts_table.sql │ ├── 003_add_user_profile.sql │ ├── 004_add_status_column.sql │ └── ... ├── scripts/ │ └── migrate.sh ├── status.json └── README.md

連番管理のメリット:

  • 適用順序が一目で分かる
  • ファイル名でどの時点のスキーマか分かる
  • 本番と開発の差分を把握しやすい

SQLファイルを直接管理する理由

Drizzle ORMのマイグレーション生成機能(drizzle-kit generate)は使わず、SQLファイルを直接作成しています。ただし、スキーマ定義自体はDrizzle ORMで管理しているため、型安全性は保たれています。

SQLファイルを直接管理する理由:

  • 複雑な変更(データ移行を伴うもの)に対応しやすい
  • 何が実行されるか完全に把握できる
  • トラブル時の原因特定が容易

🔄 開発・本番共通のマイグレーションスクリプト

Memoreruでは、開発環境と本番環境で同じスクリプトを使ってマイグレーションを適用しています。

なぜ共通スクリプトか

# 開発環境 ./database/migrations/scripts/migrate.sh dev 004_add_status_column.sql # 本番環境 ./database/migrations/scripts/migrate.sh pro 004_add_status_column.sql

共通スクリプトのメリット:

  1. リハーサル効果: 開発環境で本番と同じ手順を踏むことで、本番適用前に問題を発見できる
  2. 手順の統一: 開発はClaude Codeで直接実行、本番はスクリプト...という違いがあると事故のもと
  3. ログの一元管理: 両環境の実行ログが同じ形式で残る

環境別の違い

項目開発環境本番環境
接続情報.env.localから自動読み込み毎回手動入力
バックアップ推奨なし警告表示

本番環境の接続文字列を毎回入力するのは手間ですが、これが安全策として機能します。誤って開発環境のつもりで本番を操作する事故を防げます。

また、Claude Codeには本番環境のDB接続情報を教えていません。これにより、AIが誤って本番DBを操作するリスクを排除しています。

なお、どちらの環境でもマイグレーション適用前にpgAdminのバックアップ機能でバックアップを取得しています。万が一のロールバックに備えておくことが大切です。

🛡️ 安全に適用するための仕組み

スクリプトには以下のような安全策を組み込んでいます。

  • 確認フロー: 適用前に確認プロンプトを表示し、誤操作を防ぐ
  • 接続テスト: 適用前にDBへの接続を確認
  • ログの自動保存: すべての実行ログを logs/migrations/ に保存し、後から確認できるようにする

スクリプトの具体的な実装はClaude Codeに作成してもらいました。要件を伝えれば、環境に合わせたスクリプトを生成してくれます。

📊 status.jsonで適用状況を一元管理

開発環境と本番環境の適用状況を1つのファイルで管理しています。

{ "lastUpdated": "2025-12-04", "environments": { "dev": { "name": "開発環境", "lastApplied": "004_add_status_column", "appliedAt": "2025-12-04" }, "pro": { "name": "本番環境", "lastApplied": "003_add_user_profile", "appliedAt": "2025-11-30" } }, "pending": { "pro": ["004_add_status_column"] } }

本番未適用の確認

# pendingの一覧を表示 jq '.pending.pro' database/migrations/status.json # => ["004_add_status_column"]

開発環境で適用したマイグレーションのうち、本番にまだ適用していないものが一目で分かります。

自動更新

マイグレーション適用後、スクリプトが自動的に status.json を更新します。手動で更新する必要がないため、更新忘れを防げます。

💡 実践Tips

Tip 1: 破壊的変更は段階的に

カラム名の変更やテーブル構造の変更は、一度に行わず段階的に実行します。

-- ステップ1: 新しいカラムを追加 ALTER TABLE contents ADD COLUMN new_name TEXT; -- ステップ2: データを移行 UPDATE contents SET new_name = old_name; -- ステップ3: 古いカラムを削除(別のマイグレーションで) ALTER TABLE contents DROP COLUMN old_name;

ステップ2と3の間にアプリケーションの動作確認を挟むことで、問題があっても影響を最小限にできます。

Tip 2: ロールバック用SQLも用意

重要なマイグレーションには、ロールバック用のSQLもコメントで残しておきます。

-- マイグレーション ALTER TABLE contents ADD COLUMN status TEXT DEFAULT 'draft'; -- ロールバック(必要時のみ実行) -- ALTER TABLE contents DROP COLUMN status;

Tip 3: Claude Codeとの協働ルール

CLAUDE.mdにマイグレーション運用のルールを明記しています。

## マイグレーション運用 - 直接psqlでSQLを実行しない - 必ずmigrate.shスクリプト経由で適用 - 本番適用前に開発環境でリハーサル - 適用後はstatus.jsonをコミット

AIエージェントが誤って直接SQLを実行することを防いでいます。

✅ まとめ

DBマイグレーション運用から得た学びをまとめます。

うまくいっていること:

  • 連番ファイルで時系列管理
  • 開発・本番共通スクリプトでリハーサル
  • status.jsonで適用状況を一元管理
  • 確認フローで誤操作防止

注意が必要なこと:

  • 手動SQL管理は変更量が増えると大変になる可能性
  • 複雑なデータ移行は事前にテストデータで検証
  • ロールバック手順も事前に考えておく

個人開発でも、最初からルールを決めておくことで、後から困ることが少なくなります。

明日は「NextAuth.jsからBetter Authへ:認証ライブラリを移行した理由」について解説します。


シリーズの他の記事

  • 12/7: データベースのID設計:ID方式の選択と主キーの考え方
  • 12/9: NextAuth.jsからBetter Authへ:認証ライブラリを移行した理由

コメント

0
0
0
DBマイグレーション運用術:開発・本番環境を安全に管理する方法
0
投稿
0
フォロワー
0
いいね

プロパティ

ページ
テクノロジー
TECH

関連コンテンツ