Firebase で課金対象になるのは、データベースに保存したデータと、OSI モデルのセッション層(レイヤ 5)で発生するすべての送信ネットワーク トラフィックです。ストレージは、毎月 1 GB あたり $5 で課金され、使用量は毎日集計されます。課金はデータベースのロケーションの影響を受けません。送信トラフィックには、すべてのデータベース オペレーションから発生する接続および暗号化オーバーヘッドと、データベースの読み取りによってダウンロードされるデータが含まれます。データベースの読み取りと書き込みは、どちらも接続コストとして課金される場合があります。また、セキュリティ ルールによって拒否されたオペレーションも含め、データベースとの間で発生するすべてのトラフィックが課金対象になります。
課金対象となるトラフィックの一般的な例は、次のとおりです。
- ダウンロードしたデータ: クライアントがデータベースからデータを取得すると、ダウンロードしたデータに対する課金が発生します。一般的には、これが帯域幅コストの大部分を占めますが、これだけが課金の要因ではありません。
- プロトコルのオーバーヘッド: セッションを確立して維持するためには、サーバーとクライアント間に追加トラフィックが必要です。このトラフィックには、基盤となるプロトコルに応じて Firebase Realtime Database のリアルタイム プロトコル オーバーヘッド、WebSocket オーバーヘッド、HTTP ヘッダー オーバーヘッドが含まれます。このようなオーバーヘッドは SSL 暗号化オーバーヘッドと併せて、接続が確立されるたびに接続コストが発生する原因となります。単一リクエストの場合、それほど大きな帯域幅にはなりませんが、ペイロードが小さい場合や頻繁に短い接続を繰り返す場合は、それなりのコストとなる可能性があります。
- SSL 暗号化オーバーヘッド: セキュアな接続に必要な SSL 暗号化オーバーヘッドに関連してコストが発生します。このコストの平均は、最初の handshake で約 3.5 KB、各送信メッセージの TLS レコード ヘッダーごとに約数十バイトです。ほとんどのアプリにおいて、このコストは課金のうちわずかな割合にすぎません。ただし、多くの SSL handshake を必要とする特殊なケースの場合は、この割合が大きくなることがあります。たとえば、TLS セッション チケットをサポートしていないデバイスでは、多数の SSL 接続 handshake が必要になる場合があります。
- Firebase コンソールのデータ: Firebase コンソールから読み取りや書き込みを行ったデータに対する課金ですが、通常は Realtime Database コストの中で大きな割合を占めることはありません。
使用料金を見積もる
現在の Realtime Database の接続数とデータ使用量を確認するには、Firebase コンソールの [使用状況] タブを表示します。このタブでは、現在の請求期間、過去 30 日間、過去 24 時間の使用状況をそれぞれ確認できます。
次の指標に関する使用統計情報が表示されます。
- 接続: データベースに対して現在開いている同時リアルタイム接続数。WebSocket、ロング ポーリング、HTML サーバー送信イベントといったリアルタイム接続が含まれます。RESTful リクエストは含まれません。
- ストレージ: データベースに保存されているデータ量。Firebase ホスティングや、その他の Firebase プロダクトを使用して保存したデータは含まれません。
- ダウンロード: データベースからダウンロードされたすべてのバイト数で、プロトコルや暗号化のオーバーヘッドも含まれます。
- 読み込み: このグラフは、該当する 1 分の間隔で、データベースがリクエストの処理にどれだけ使用されているかを示します。データベースが 100% に近づくと、パフォーマンスの問題が発生することがあります。
使用を最適化する
データベースの使用量と帯域幅コストを最適化するおすすめの方法としては、以下のものが挙げられます。
- ネイティブ SDK を使用する: REST API ではなく、アプリのプラットフォームに対応した SDK をできるだけ使用します。SDK は開いている接続を維持するため、REST API を使用した場合に発生する追加の SSL 暗号化コストが削減されます。
- バグをチェックする: 帯域幅コストが予想以上に高い場合は、アプリで同期しているデータ量や同期の頻度が当初想定していたよりも大きくなっていないか確認します。問題を特定するには、プロファイラ ツールを使用して読み取りオペレーションを測定します。このとき、Android、Objective-C、ウェブの各 SDK のデバッグ ロギングはオンにします。アプリのバックグラウンド プロセスと同期プロセスを確認して、すべてが想定どおりに機能していることを確認します。
- 接続数を減らす: 可能であれば、接続の帯域幅を最適化してみます。小さな REST リクエストが頻繁に発生すると、ネイティブ SDK を使用した単一の接続を継続的に維持するよりもコストがかかることがあります。REST API を使用する場合は、HTTP keep-alive やサーバー送信イベントの使用を検討してください。これにより、SSL handshake によるコストを削減できます。
- TLS セッション チケットを使用する: TLS セッション チケットを発行することで、接続再開時の SSL 暗号化オーバーヘッド コストを削減します。これは、データベースに対してセキュアな接続を頻繁に行う必要がある場合に特に役立ちます。
- クエリ用にインデックスを作成する: データのインデックスを作成して、クエリに使用される総帯域幅を減らします。これにはコスト削減とデータベースのパフォーマンス向上という二重の利点があります。プロファイラ ツールを使用して、データベース内でインデックス付けされていないクエリを検索します。
- リスナーを最適化する: リッスン オペレーションから返されるデータを制限するクエリを追加し、データの更新のみをダウンロードするリスナー(たとえば、
once()
ではなくon()
)を使用します。また、リスナーをできるだけ経路の下流に配置して、同期させるデータの量を制限します。 - ストレージ コストを削減する: クリーンアップ ジョブを定期的に実行して、データベース内の重複データを削減します。
- ルールを使用する: コストがかかる可能性のある、未承認のオペレーションがデータベース上で行われないようにします。たとえば、Firebase Realtime Database セキュリティ ルールを使用して、悪意のあるユーザーがデータベース全体を繰り返しダウンロードするというシナリオを避けることができます。Firebase Realtime Database ルールの使用をご覧ください。
アプリに適した最適化プランは、ユースケースによって異なります。また、ここで説明した方法がすべてではありません。Slack チャンネルや Stack Overflow では、Firebase のエキスパートがさまざまなアドバイスやヒントを紹介しています。