プロダクトを構築

データベースとマイグレーション

PostgreSQL の運用先を選び、実行中のアプリを壊さず Drizzle の変更をリリースします。

スターターのコミット 7580470 で検証済みです。

このページを終えると、各環境で使う DB、スキーマ変更をレビュー可能な SQL にする方法、アプリのリリースとは分けて適用する方法が分かります。

スターターは複数の DB アダプターを用意せず、PostgreSQL と Drizzle を採用しています。ローカルでは pnpm setup で Docker 上の PostgreSQL を使えます。本番では、互換性のあるマネージド PostgreSQL または自社運用の PostgreSQL を選び、DATABASE_URL を設定します。src/db/schema.ts がスキーマの正本で、src/db/migrations/ にコミットされた SQL がデプロイ履歴です。db() を呼べるのは src/models/** だけです。

ローカル手順

pnpm setup は開発用とテスト用の DB を分けて作ります。テスト DB の名前には test が必要で、安全機構はそれ以外の DB の全行削除を拒否します。

スキーマ変更後:

pnpm db:generate
pnpm db:migrate
pnpm test:db:setup
pnpm test:db

生成された SQL と meta/_journal.json をコードと一緒にコミットし、デプロイ済みのマイグレーションは編集しません。

本番手順

アプリのデプロイ時にマイグレーションは自動実行されません。DB とアプリを別々に監視し、再試行し、リリースできるようにする既定の安全策です。

pnpm db:check:prod
pnpm db:migrate:prod

本番用の実行処理は、非対話で PostgreSQL のアドバイザリーロックを取得し、チェックサムを検証します。先にバックアップを取り、スキーマとアプリを別々にリリースしても新旧コードの両方が動く、追加してから削除する段階的な変更にします。

データ規約

  • 数値 id は内部用、公開 API は uuid を使います。
  • 金額は最小通貨単位の整数と通貨コードで保存します。
  • テナントに属する行は org_uuid を持ち、すべてのモデルクエリで組織を限定します。
  • 冪等性キーと取引番号は、DB の一意制約で守ります。
  • 広範な外部キー結合を意図的に避け、削除順序と参照確認はサービスとデータライフサイクル方針が担います。
  • 予約では PostgreSQL の排他制約も使い、仮押さえ・確定済みの時間枠が重複するのを防ぎます。

本番前に決めること

  • マイグレーションを CI のリリースジョブと運用担当者のどちらが実行するか決めます。各 Web インスタンスからは実行しません。
  • データの価値に見合うバックアップ・復元方針を決めます。マイグレーションロックはバックアップの代わりではありません。
  • 外部キーを少なく保つか、削除・保持の規則を定義したうえで厳しい制約を加えるか決めます。どちらもテナント間の安全性を保つ必要があります。
  • 無停止を目指す場合は、追加してから削除する段階的な変更を優先します。破壊的な一段階の名前変更は簡単ですが、スキーマとコードのリリースを結合し、ロールバックを危険にします。

pnpm db:check:prod が予想どおりの未適用一覧を示し、バックアップが最新で、ステージング環境の複製で検証済みであり、展開中に旧・新両方のアプリ版が動くなら、本番マイグレーションの準備は完了です。

本番データの契約を変える前に、スターターの docs/database.mdDEPLOYMENT.md を読んでください。コードの置き場所はアーキテクチャとエラー契約、認証用 ID と公開 ID の区別は顧客認証で確認できます。

データベースとマイグレーション · Sushi SaaS