外部CRM(顧客管理システム)に蓄積された数万件のチャット履歴を、AIアシスタントが検索できる形で自社DBに持たせたい、という要件に直面したインフラ担当者向けの内容です。Firebase(Googleのモバイル・Webアプリ開発基盤)の中でも、Realtime DatabaseとFirestoreのどちらを選ぶかは、書き込み量が増えた瞬間に効いてくる設計判断です。
実際にあった事例では、約48,000件の連絡先と日々増え続けるチャット履歴を、外部CRMからその都度取得するのではなく、自社DBに永続化して検索対象にする方針転換がありました。この規模になった時点で、単なる機能追加ではなく明確なアーキテクチャ決定として扱う必要があります。SREやインフラ担当者にとっても、外部システム連携が「ちょっとした機能」から「可用性・コストに直結する基盤」に変わる典型的な瞬間です。
何が起きたのか:スケールが変わると設計が変わる
元の構成では、管理パネルの機能として外部CRMのAPIをその都度呼び出し、パイプライン(商談のステージ管理)や会話履歴を表示していました。これは十分に動いていた既存機能で、新しい要件のために書き直す必要はありませんでした。
ところが「全連絡先と全チャットを自社DBに保存し、AIが検索できるようにしたい」という要求が来た時点で話が変わります。数万件規模のデータを都度APIで引くのではなく、永続化して増分更新するモデルに切り替える必要が出てきたのです。
これはWebhook(外部システムからのイベント通知を受け取る仕組み)を使った同期処理と、ベクトル検索(文章の意味的な近さで検索する仕組み)という2つの新しい要素を持ち込む決定でした。
Realtime DatabaseではなくFirestoreを選ぶ理由
Firebaseには昔からあるRealtime Databaseと、後発のFirestoreという2つのNoSQLデータベースがあります。両者はよく似た用途で使われますが、書き込みが増えるスケールでの挙動が大きく異なります。
Realtime Databaseは、ノード単位でデータを持ち、そのノードに変更があるたびに接続中の全クライアントへ丸ごと再送信します。たとえば contacts/{id}/messages のようなパスにメッセージを溜め込む設計だと、連絡先とチャットが増えるほど再送信されるデータ量が増え、最初の書き込みラッシュからすぐに帯域の問題になります。
Firestoreはこの弱点を構造的に避けています。インデックス付きクエリ、親ドキュメントを書き換えずに増え続けるサブコレクション、そしてネイティブのベクトル検索対応です。特にベクトル検索は、全チャットを横断した意味検索を実現するうえで決定的な理由になっています。別途ベクトルDB(Pinecone やWeaviateなど)を用意せずに、Firestore単体で「このコンタクトが何を書いたか」「あるトピックについて誰が返信したか」といった問い合わせに答えられる構成が組めるからです。
サーバーサイド検索とページネーションの設計判断
数万件の連絡先をクライアント側に全件ロードしてフィルタするのは、パフォーマンスとメモリの両面で非現実的です。正しいアプローチはサーバーサイド検索で、キー入力ごとに(400msのデバウンス、つまり短時間の連続入力をまとめて1回にする仕組みを挟んで)バックエンド関数がCRM自体の検索エンジンにクエリを転送します。
画面上でユーザーが見るのは「30件ずつ読み込み、続きを読むボタンで追加取得する」というページ単位の表示ですが、検索対象そのものは常に全件です。ここは実装時に混同しやすいポイントで、UIの表示件数と検索スコープを分けて考える必要があります。
また、外部CRMの検索が「部分一致」であってあいまい検索(タイプミスや語順違いを許容する検索)ではない、という制約も見逃せません。この制約は後段のAIロジックでも障害要因になり得るため、UI設計とAI側のクエリ生成ロジック両方で前提として共有しておくべき情報です。
障害対応・運用の観点で見るべきポイント
この構成をSRE視点で見ると、確認すべき箇所はいくつかに絞られます。
- Webhook受信の再送設計:外部CRM側の再送ポリシーとFirestore書き込みの冪等性(同じイベントを複数回処理しても結果が変わらない設計)が噛み合っているか
- カーソル・ページネーションの進行状態:同期処理でカーソルが止まったまま気づかない、という事故は監視で検知できるようにしておく必要があります
- Firestoreの書き込みコスト:ドキュメント単位の課金モデルのため、チャット1件ごとに書き込みが発生する設計だとコストが線形に増える点は事前に見積もっておくべきです
- ベクトル検索のインデックス構築タイミング:新規チャット追加時にインデックスがいつ反映されるか(結果整合性の遅延がSLOに影響しないか)
SLO(サービスレベル目標)を設計する際は、「AIアシスタントが最新の会話までどれくらいの遅延で検索対象にできるか」を明示的な指標にしておくと、Webhook同期の遅延やベクトルインデックス反映の遅延が可視化されます。単に「検索できる」ではなく「何分以内に検索対象になる」という形でSLOを立てるのが実務的です。
今日確認できること
すでにFirebaseを使っている、あるいは今後外部CRM連携を自社DBに持たせる予定があるなら、以下を確認しておくと判断がしやすくなります。
- 現在の書き込み頻度と将来のデータ増加率を見積もり、Realtime DatabaseのノードサイズがどれだけのペースでKB単位から増えるか計算する
- Firestoreのベクトル検索機能が利用可能なリージョン・SDKバージョンかどうかを、Firebase公式ドキュメントの「Vector search」ページで確認する
- Webhook受信エンドポイントに再送・重複配信を想定したidempotencyキー(重複処理を防ぐ識別子)の設計が入っているか確認する
- 既存のバンドル(ビルド時にまとめるコード群)構成でFirestoreの依存関係が正しく解決されているか、ローカルビルドとCI環境の両方で確認する
最後の点は特に見落とされやすい部分です。ライブラリのバンドリングエラーは、ローカルでは通っていてもCI/CDパイプラインの環境差で再発することがあり、依存関係の固定(package.jsonのバージョン指定やlockファイルの整合性)を見直す価値があります。
まとめ
外部システムのデータを自社DBに取り込んでAI検索基盤にする作業は、機能追加ではなくアーキテクチャ決定として扱うべき規模になることがあります。
Realtime Databaseの全ノード再送という制約とFirestoreのインデックス付きクエリ・ネイティブベクトル検索という選択肢を比較し、データ増加率に応じて選び直すのが現実的な判断基準です。
Webhook同期の冪等性、カーソル進行の監視、書き込みコストの見積もり、そしてSLOとしての検索反映遅延の明示化は、導入前に一度整理しておく価値があります。
まずは自社のデータ増加ペースとFirebase公式ドキュメントのベクトル検索対応状況を確認するところから始めてみてください。