マルチテナント設計
方針
全テナントが同一スキーマを共有し、各行を tenant_id で分離する
共有DB + 行分離 方式を採用。さらに PostgreSQL の
Row-Level Security (RLS) でテナント越境を DB レベルで防ぎます(多層防御)。
仕組み
リクエスト └─ テナント解決 (現状: x-tenant-id ヘッダー / 将来: JWT claim) └─ AsyncLocalStorage にテナントIDを格納 └─ withTenant(db, tenantId, fn) └─ トランザクション内で set_config('app.current_tenant', ...) └─ RLS ポリシーが tenant_id = current_tenant_id() で行を絞り込み- アプリは RLS が効く制限ロール
app_userで接続する。 - マイグレーションのみ、RLS をバイパスできるオーナーロールで実行する。
- ポリシー定義は
packages/db/sql/rls.sql。
新しいテナント所属テーブルを追加するとき
tenant_idカラム + テナント内一意制約 +tenant_idインデックスを付ける。packages/db/sql/rls.sqlのtenant_tables配列にテーブル名を追記する。- クエリは必ず
withTenant経由で実行する(直接db.select()を呼ばない)。
詳細な決定経緯は ADR-0003 を参照。