SaaSデータベースアーキテクチャの設計
最初の1週間に行う誤ったデータベースの決定は、その後何年もの間、あなたを苦しめることになります。
SaaSの創業者には、マルチテナンシー、課金、そして成長に対応できるスキーマが必要です。設計を誤ると、半年後にはシステム全体を書き直すことになります。
以下に、本番環境に耐えうるスキーマの構築方法をまとめます。
1. テナント戦略の選択
顧客間でデータを分離しなければなりません。
• 行レベル (Shared DB): 低い複雑性。ほとんどのスタートアップに最適。すべてのクエリに WHERE organization_id = ? フィルタを使用します。
• スキーマレベル (Separate Schemas): 中程度の複雑性。規制要件への対応に適しています。
• データベースレベル (Separate DBs): 高い複雑性。エンタープライズクライアントに最適です。
新規プロダクトの90%において、行レベルのマルチテナンシーが正しい選択です。
2. 正しいエンティティ階層
ユーザーに直接課金してはいけません。ユーザーは入れ替わりますが、組織は存続します。
階層は以下のようになるべきです: User ── MemberOf ── Organization ── Subscription ── Invoice
• Users: このテーブルは識別のみに使用します。攻撃を防ぐためにUUIDを使用してください。 • Organizations: これがテナントの境界となります。サブスクリプションは常に組織に紐付けてください。 • Memberships: ユーザーと組織を紐付けるために中間テーブル(join table)を使用します。ロール(役割)はユーザーテーブルではなく、ここに保存してください。
3. 課金とサブスクリプション
is_active のような単純な boolean 型は決して使用しないでください。データが混乱する原因になります。
サブスクリプションにはステートマシンを使用してください。一般的なステートには以下が含まれます:
• trialing
• active
• past_due
• canceled
• expired
• incomplete
これにより、手動でのデータ修正を行うことなく、支払いの失敗や猶予期間(grace periods)を処理できるようになります。
4. 金銭と請求
金銭的なエラーを避けるため、以下の厳格なルールに従ってください:
• 金銭に対して FLOAT や REAL は決して使用しないでください。セント単位を保存するために整数(integer)を使用します。例えば、$29.99 は 2999 となります。
• invoice_line_items テーブルを使用してください。税務報告や返金にこれが必要になります。
• 顧客のプロダクト利用量に基づいて課金する場合は、usage_events テーブルを使用してください。
5. パフォーマンスのヒント
• 外部キーにインデックスを貼る。
• ステータス列にインデックスを貼る。
• タイムスタンプ列にインデックスを貼る。
• N+1 クエリを避ける。JOIN を使用して、1回のクエリで組織とサブスクリプションのデータを取得するようにします。
優れたスキーマは、機能しているときは意識されることがありません。しかし、失敗したときには壊滅的な影響を及ぼします。
組織(Organization)のために構築してください。ステートマシンを使用してください。お金は整数として保存してください。
Optional learning community: https://t.me/GyaanSetuAi
