ADR-003: MongoDB採用
ステータス
採用済み
意思決定者
- 太田裕貴(CTO)
- バックエンドチーム
決定日
2021年頃(プロジェクト初期)
背景(Context)
Qudenは動画ベースのナレッジ共有SaaSであり、以下のようなデータを扱います:
現状の課題
- 動画メタデータ(タイトル、説明、タグ、サムネイル、再生時間等)の柔軟な管理が必要
- ユーザー生成コンテンツのため、スキーマが頻繁に変更される可能性
- 動画に紐づく多様な付加情報(コメント、リアクション、ステップガイド等)の管理
- 動画検索機能の実装が必須(全文検索、メタデータ検索)
- 将来的なスケールを見越したデータベース選択
解決したいこと
- 柔軟なスキーマ設計でプロダクトの成長に対応
- 高速な全文検索機能の実現
- スケーラビリティの確保
- 開発速度の向上(スキーマ変更の容易さ)
要件(Requirements)
機能要件
- 動画メタデータの永続化
- ユーザー、ワークスペース、アイテム(動画)等のエンティティ管理
- 全文検索機能(動画のタイトル、説明、タグ等)
- 関連データの柔軟な紐付け(1対多、多対多)
非機能要件
- パフォーマンス: 読み取りが多いワークロードに対応
- スケーラビリティ: ユーザー数・動画数の増加に対応できるスケールアウト
- 可用性: 高可用性(99.9%以上のアップタイム)
- 保守性: スキーマ変更が容易
制約条件
- 技術的制約:
- TypeScriptとの親和性が高いこと
- マネージドサービスが利用可能であること(運用負荷の削減)
- ビジネス的制約:
- 初期コストを抑えつつ、スケールに応じた従量課金
- 時間的制約:
- 早期のMVPリリースが求められる
検討した選択肢
選択肢1: PostgreSQL(リレーショナルDB)
概要
オープンソースのリレーショナルデータベース。ACID特性を持ち、トランザクション処理に強い。
メリット
- 強力なトランザクション機能(ACID保証)
- 複雑なJOIN操作が可能
- 豊富なエコシステムとツール
- 全文検索機能(pg_trgm、tsvector)もサポート
- AWS RDSでマネージドサービスが利用可能
デメリット
- スキーマ変更時にマイグレーションが必要(ALTER TABLE等)
- JSONBを使えば柔軟性は確保できるが、リレーショナルの恩恵が薄れる
- 水平スケーリングが困難(シャーディングが複雑)
- 動画メタデータのような階層的データの扱いが冗長になりがち
実装コスト
- 初期実装: 中(スキーマ設計に時間がかかる)
- 学習コスト: 低(チームメンバーが慣れている)
- 保守コスト: 中(マイグレーション管理が必要)
選択肢2: MongoDB(ドキュメントDB)
概要
NoSQLドキュメント指向データベース。JSON形式でデータを保存し、柔軟なスキーマ設計が可能。
メリット
- スキーマフレキシビリティ: スキーマレスで、プロダクトの成長に柔軟に対応
- Atlas Search: MongoDB Atlas上で強力な全文検索機能を提供(Elasticsearch不要)
- Materialized View: 集計クエリのパフォーマンス最適化
- Atlas Triggers: データ変更時の自動処理(リアルタイムイベント)
- 水平スケーリング: シャーディングによるスケールアウトが容易
- TypeScriptとの親和性: JSON形式のデータがそのまま扱える
- Atlas マネージドサービス: 運用負荷が低い
デメリット
- トランザクション処理が限定的(単一ドキュメントは保証されるが、複数ドキュメント間のトランザクションは制約あり)
- JOIN操作が複雑(
$lookupは使えるが、リレーショナルDBほど効率的ではない) - 学習コストがリレーショナルDBより若干高い
- 適切なインデックス設計が重要(パフォーマンスに直結)
実装コスト
- 初期実装: 低(スキーマ設計が柔軟)
- 学習コスト: 中(NoSQLの概念理解が必要)
- 保守コスト: 低(スキーマ変更が容易)
選択肢3: DynamoDB(AWSのキーバリューDB)
概要
AWSが提供するフルマネージドNoSQLデータベース。高いスケーラビリティと低レイテンシが特徴。
メリット
- AWS統合が容易
- ほぼ無限のスケーラビリティ
- 完全マネージドでサーバーレス
- 低レイテンシのキーバリューアクセス
デメリット
- 柔軟なクエリが困難(パーティションキー、ソートキーに依存)
- 全文検索機能がない(別途Elasticsearchが必要)
- セカンダリインデックスのコストが高い
- 複雑なクエリには向かない
- 学習コストが高い(DynamoDB固有の設計パターン)
実装コスト
- 初期実装: 高(設計パターンの学習が必要)
- 学習コスト: 高
- 保守コスト: 低(マネージドサービス)
決定(Decision)
選択した技術: MongoDB(MongoDB Atlas)
選択理由
要件との適合性
- 動画メタデータのような階層的で柔軟なデータ構造に最適
- Atlas Searchにより、別途Elasticsearchを導入せずに全文検索を実現
- Materialized Viewで集計クエリのパフォーマンスを最適化
- スキーマレスのため、プロダクトの成長に柔軟に対応可能
技術的妥当性
- TypeScriptとの親和性が高く、開発速度が向上
- MongooseなどのODM(Object Document Mapper)が充実
- 水平スケーリングが容易で、将来的なユーザー増加に対応可能
- Atlas Triggersでリアルタイム処理が実装可能
コスト対効果
- 初期実装コストが低く、MVPの早期リリースに寄与
- マネージドサービス(Atlas)により、運用負荷とコストを削減
- 従量課金で、プロダクトの成長に応じてスケール可能
将来性
- MongoDB社の継続的な機能追加(Atlas Search、Triggers等)
- エコシステムが充実しており、コミュニティサポートも豊富
- AWSやGCPとの統合も容易
実装方針
MongoDB Atlas の採用
- フルマネージドサービスでインフラ管理の負荷を削減
- 本番環境、ステージング環境、開発環境を分離
Mongoose ODMの使用
- TypeScriptとの統合が容易
- スキーマ定義による型安全性の確保
- バリデーション機能の活用
Atlas Searchの活用
- 動画のタイトル、説明、タグ等の全文検索に使用
- Materialized Viewで検索パフォーマンスを最適化
適切なインデックス設計
- 頻繁に検索されるフィールドにインデックスを作成
- Compound Indexで複合条件検索を最適化
受け入れたトレードオフ
トレードオフ1: トランザクション処理の制約
- 影響: 複数ドキュメント間のACIDトランザクションが限定的
- 受け入れ理由:
- Qudenのユースケースでは、強いトランザクション保証が必要な箇所は限定的
- 単一ドキュメント内での操作でほとんどのケースをカバーできる
- 軽減策:
- 決済処理など、強いトランザクション保証が必要な箇所はStripe等の外部サービスに依存
- アプリケーションレベルでのエラーハンドリングと冪等性の確保
トレードオフ2: JOIN操作の複雑さ
- 影響: リレーショナルDBのような効率的なJOINができない
- 受け入れ理由:
- ドキュメント指向の設計により、多くのケースでJOINが不要
- 必要な場合は
$lookupやアプリケーション側でのデータ結合で対応可能
- 軽減策:
- 非正規化(データの埋め込み)により、JOIN不要な設計を心がける
$lookupの使用を最小限に抑える
結果(振り返り)
うまくいったこと(Pros)
- 開発速度の向上: スキーマ変更が容易で、プロダクトの成長に柔軟に対応できた
- Atlas Searchの強力さ: 別途Elasticsearchを導入せずに全文検索を実現できた
- 運用負荷の削減: マネージドサービスにより、インフラ管理の負荷が大幅に削減された
- TypeScript統合: Mongooseとの組み合わせで、型安全なコードが書けた
うまくいかなかったこと(Cons)
- インデックス設計の重要性: 適切なインデックスがないとパフォーマンスが大きく劣化することがあった
- JOIN操作の複雑さ: 一部のクエリで
$lookupを多用し、パフォーマンスに影響が出た - 学習コスト: チームメンバーがリレーショナルDBに慣れていたため、NoSQLの概念理解に時間がかかった
学び
- 非正規化の重要性: できるだけデータを埋め込むことで、JOIN不要な設計にすることが重要
- Atlas Searchのポテンシャル: Materialized Viewと組み合わせることで、複雑な検索クエリも高速に処理できる
- インデックス戦略: 本番環境でのクエリパフォーマンスをモニタリングし、適切なインデックスを追加することが重要
今後の改善点
- クエリパフォーマンスの継続的な最適化: MongoDB CompassやAtlas Monitoringを活用した定期的なレビュー
- トランザクション処理の再検討: 将来的に複雑なトランザクションが必要になった場合の対応策を検討
- コスト最適化: データ量の増加に伴い、Atlas のコスト最適化を定期的に実施