Firexportブログ

Firestore Enterprise と Standard: 新しいアプリは Enterprise で始めよう

Firestore データベースを作るときに選ぶエディション(Standard または Enterprise)は、あとから変えられません。Enterprise エディションの Native モードが 2026 年 4 月に一般提供(GA)になった今、新しいアプリは Enterprise で始めるほうが有利です。ただし、インデックスとクライアントからのアクセスを自分で管理することが条件です。

要点

  • あとで行き詰まりにくいほうを選びましょう。Standard の限界はデータを移さないと解消できませんが、Enterprise の問題はたいていインデックスをデプロイすれば解決します。理由
  • コードはそのまま、クエリは増える。リアルタイム リスナー、オフライン、セキュリティ ルールは Standard と同じで、検索・集計・結合ができる Pipeline クエリが加わります。増えるもの
  • インデックスを使う読み取りは安くなります。4 KiB 以下のドキュメントを ID で読むと Standard の 6 分の 1 です。書き込みはインデックスが多いほど高くなり、削除は常に高くなります。料金の比較
  • インデックスとアクセスは自分で管理します。インデックスのないクエリはエラーなしでコレクション全体を読み、他人が意図的にそうさせることもできます。守ること

Enterprise をデフォルトにする理由

1. 変えられないから、行き詰まりにくいほうへ

エディションはデータベースを作るときに決まり、その後は変わりません。変えるには、新しいデータベースにデータを移し、インデックスと TTL・バックアップの設定を作り直し、アプリが新しいデータベースを参照するように新しいバージョンをリリースする必要があります(移行ガイド)。

だから、あとで行き詰まりにくいほうで始めるべきです。Standard で行き詰まるのは検索、集計、結合といった機能なので、移行するか構造を変えて回避するしかありません。Enterprise で行き詰まるのはたいていインデックスの不足なので、コードとデータはそのままで、インデックスをデプロイすれば済みます。

2. 同じコードに、クエリが加わる

Enterprise の Native モードは、Standard と同じ Firebase SDK と同じクエリ(Core オペレーション)を使います。where()、orderBy()、onSnapshot() リスナー、オフライン キャッシュ、セキュリティ ルールはそのまま動き、ローカル エミュレータ、Cloud Functions(第 2 世代)のトリガー、Standard と同じリージョン、Spark プランの無料枠にも対応しています。違うのは並べ替えです。並べ替えの値が同じドキュメント同士の順序をドキュメント ID で決めてくれないので、カーソルでページ送りをするなら orderBy にドキュメント ID を加えてください。

その上に Pipeline クエリが加わります。Standard では回避策が必要だったことが、クエリ 1 つで済みます。

やりたいことStandardEnterprise
本文の全文検索外部の検索サービス(Algolia など)に同期テキスト検索
半径内の場所を探すgeohash フィールドを作って範囲クエリ地理空間検索
文字列の一部・正規表現で探す前方一致のみstr_contains、regex_match
グループごとの合計、ユニークな値の数グループごとに集計するか、カウンタ ドキュメントを維持aggregate ステージ 1 つ
別のコレクションと合わせて読む非正規化するか、何度も読むサブクエリによる結合
条件に合うドキュメントの一括更新・削除読み取ってバッチで書き込むスクリプトupdate・delete ステージ
値の重複を防ぐその値を ID にしたドキュメントとトランザクションユニーク インデックス

テキスト検索・地理空間検索と一括更新・削除(DML)は 2026 年 10 月に一般提供になりました。ただし Pipeline は 1 回実行して終わる読み取りなので、リアルタイム リスナーとオフラインはなく、セキュリティ ルールは Pipeline では定数と比較する単純なフィルタしか理解しません。画面の一覧とリアルタイムの更新は Core クエリ、検索・集計・レポートは Pipeline と分け、複雑な Pipeline はサーバー(Admin SDK、Cloud Functions)で実行しましょう。

3. インデックスを使う読み取りは安い

Standard はドキュメントの数で、Enterprise は読み書きしたバイト数で料金を計算します。us-central1 の 2026 年 11 月時点の料金です。

StandardEnterprise
読み取り100 万ドキュメントで $0.304 KiB ごとに 1 ユニット、100 万ユニットで $0.05
書き込み100 万ドキュメントで $0.90、インデックスの更新は無料1 KiB ごとに 1 ユニット、100 万ユニットで $0.26。インデックス エントリごとに 1 ユニット追加
削除100 万ドキュメントで $0.10書き込みユニット(ドキュメント + インデックス エントリ)
リアルタイム アップデート読み取りとして計算、100 万件で $0.304 KiB ごとに 1 ユニット、100 万ユニットで $0.30。4 KiB 以下のドキュメントは同じ料金
保存1 GiB あたり月約 $0.15。全フィールドの自動インデックスも容量に含む1 GiB あたり月約 $0.23。自分で作ったインデックスだけを含む
1 日の無料枠読み取り 5 万、書き込み 2 万、削除 2 万読み取り 5 万、書き込み 4 万、リアルタイム 5 万ユニット
  • 読み取り: 4 KiB 以下のドキュメントを ID で読むと Enterprise は 6 分の 1 で、24 KiB までは同じか安くなります。クエリはインデックスを読む分が加わるので、結果が 1 件なら 3 分の 1、件数が多いほど 6 分の 1 に近づきます。
  • 書き込み: 1 KiB のドキュメントを新しく書くとき、インデックス エントリが 2 つまでなら Enterprise が安く(100 万件で $0.78)、3 つ以上だと高くなります($1.04)。インデックスのあるフィールドを変える更新は、変わるエントリごとに 2 ユニットかかるので、より早く高くなります。
  • 削除: 最小のドキュメントでも 1 ユニット($0.26)なので、Standard($0.10)より常に高くなります。

書き込みより読み取りがずっと多いアプリなら、Enterprise のほうが安くなります。書き込みと削除が多いアプリは、ドキュメントのサイズとインデックスの数で先に計算してみてください。

代償: インデックスとアクセスは自分で管理する

Standard はインデックスを使えるクエリしか実行しません。フィールドごとにインデックスが自動で作られ、複合インデックスが必要なクエリは、そのインデックスを作るリンク付きのエラーを返します。そのため、クエリの費用は結果の件数だけで決まります。

Enterprise はインデックスを自動で作らず、インデックスがなくてもクエリを実行します。その代わりコレクション全体を読み、読んだバイト数だけ課金されます。並べ替えもメモリ上で行うので、クエリあたりのメモリ上限(128 MiB)に達することがあります。エラーが出ないので、ドキュメントが数十件の開発中には気づかず、データが増えてから表に出ます。

ユーザー名で 1 人を探すクエリを 100 万回実行したときの料金です。ドキュメントは 2 KiB で、1 行目は Google の料金の例、2 行目は同じ計算をドキュメント 10 万件に広げたものです。

コレクションStandard(自動インデックス)Enterprise(インデックスあり)Enterprise(インデックスなし)
ドキュメント 100 件$0.30$0.10$2.50
ドキュメント 10 万件$0.30$0.10$2,500

インデックス 1 つで、同じクエリの料金に 2 万 5 千倍の差が出ます(100,000 × 2 KiB ÷ 4 KiB = クエリ 1 回で 50,000 ユニット)。

この差は他人にも使えます。クライアントが一覧を読めるコレクションなら、誰でもインデックスのないフィールドでフィルタを付けて、読める範囲全体をスキャンさせられます。一致するドキュメントがないので limit も効かず、セキュリティ ルールはクエリに付け足されたフィルタを防げません。Standard ではこのクエリはエラーで終わります。

守ること 4 つ

  1. クエリを書くときにインデックスも書きます。増え続けるコレクションに使う where・orderBy の組み合わせごとに、インデックスを firestore.indexes.json に書き、firebase deploy --only firestore:indexes でデプロイします。Standard が自動で作っていた単一フィールドのインデックスも自分で書きます。ドキュメント ID で読むときはインデックスは要りません。次は where('authorId', '==', uid).orderBy('createdAt', 'desc') 用のインデックスです。
    {
      "indexes": [
        {
          "collectionGroup": "posts",
          "queryScope": "COLLECTION",
          "fields": [
            { "fieldPath": "authorId", "order": "ASCENDING" },
            { "fieldPath": "createdAt", "order": "DESCENDING" }
          ]
        }
      ]
    }
  2. リリース前に Query Explain で確認します。Firebase コンソールで Firestore のデータ(Data)タブにあるクエリ エディタ(Query Editor)で同じ条件を実行し、Query Explain タブを開きます。実行ツリーのいちばん下が TableScan なら、インデックスなしでコレクション全体を読んでいます。
  3. クライアントのアクセスを絞ります。App Check を適用してアプリ以外からのリクエストを拒否し、セキュリティ ルールで一覧の読み取りを resource.data.ownerId == request.auth.uid のように、インデックスのあるフィールドの等価条件に縛ります。そうすれば、スキャンが起きてもそのユーザーのドキュメントの中で終わります。
  4. Query Insights と予算アラートを有効にします。Query Insights はよく実行されるクエリとそのパフォーマンスを示し、インデックスが必要な場所を教えてくれます。Blaze プランなら Cloud Billing の予算アラートも設定しておきましょう。

Enterprise で始める

Firebase コンソールの Firestore でデータベースの作成(Create database)をクリックし、Enterprise と Native モードを選んで、ID とロケーションを決めます。リアルタイム アップデート(Realtime Updates)はオンのまま(デフォルト)にしてください。あとから変えられないので、オフで作るとリスナーを使えないデータベースになります。そのあと、次の 3 点が Standard と違います。

  1. コードにデータベース ID を渡します。Enterprise のデータベースは自分で名前を付けたデータベースで、(default) は Standard にしかありません。SDK は指定しない限り (default) に接続します。
    // Web
    const db = getFirestore(app, 'app-db');
    
    // Android (Kotlin)
    val db = FirebaseFirestore.getInstance("app-db")
    
    // iOS (Swift)
    let db = Firestore.firestore(database: "app-db")
    
    // Flutter
    final db = FirebaseFirestore.instanceFor(
        app: Firebase.app(), databaseId: 'app-db');
  2. firebase.json にデータベースとエディションを書きます。ルールとインデックスがそのデータベースにデプロイされ、エミュレータも Enterprise で起動します。データベースはコンソールで先に作ってください。書かれたデータベースが存在しないと firebase deploy が代わりに作りますが、Firebase CLI 15.12 はその際、Firebase SDK から使えない MongoDB 互換モードで作ります。
    {
      "firestore": {
        "database": "app-db",
        "edition": "enterprise",
        "rules": "firestore.rules",
        "indexes": "firestore.indexes.json"
      }
    }
  3. 無料枠は最初に作ったデータベース 1 つにだけ付きます。使っていない Standard データベースがプロジェクトにあるなら、それを削除してから Enterprise を作ってください。そうすれば無料枠が Enterprise に付きます。

Standard のほうがまだ向いているケース

  • すでに Standard で動いているアプリ。Pipeline が本当に必要になるまでは移さないでください。
  • クエリとインデックスを管理する人がいないプロジェクト。インデックスのないクエリをそもそも実行しない Standard が安全装置になります。
  • 大きな公開コレクションをクライアントが直接読むアプリ。ルールで範囲を絞れない公開の一覧は、誰でも全体スキャンを起こせます。
  • 書き込み・削除が多い、または大きなドキュメントを主に読むアプリ。上の損益分岐点を超えるなら Standard のほうが安くなります。
  • (default) データベースや Cloud Functions 第 1 世代を前提にしたツールを使う必要があるとき。Enterprise は名前付きのデータベースで、第 1 世代のトリガーに対応していません。

出典

すべての記事 →