皆さん、こんにちは。okamoです。
現在、Firebase StudioやGoogle AI StudioでWebサイトを運用している方で、「なんだかページの表示が遅いな」と感じている方はいませんか? 実は、Firebase StudioやGoogle AI Studioの「Publish」ボタンを使った自動デプロイは、USリージョン(us-central1やus-west1など)に固定されてしまいます。もし、データベースであるFirestoreを東京リージョン(asia-northeast1)に設定している場合、サーバーとデータベース間で太平洋を往復する通信が発生し、大きなレイテンシ(遅延)が生じてしまうのです。
今回は、このサイト(okamoのhomepage)をApp Hosting(US)+Firestore(東京)の構成から、Cloud Run(東京)+Firestore(東京)へと移行し、表示速度を大幅に改善させた際の実録をご紹介します。Claudeをアシスタントに迎え、エンジニア向けに移行のポイントをまとめました。
移行の背景と技術的課題
Firebase StudioやGoogle AI Studioの「Publish」ボタンを使った自動デプロイを行うと、バックエンドがCloud Run (us-west1)などで立ち上がります。一方で、本番のFirestoreは東京リージョンです。 Claudeに相談したところ、「USと東京間のネットワークRTT(ラウンドトリップタイム)は約100-150msあるため、サーバーサイドレンダリング(SSR)で複数回Firestoreにアクセスするページでは致命的な遅延になる」と指摘されました。東京リージョン同士にすれば数msで済むため、大きなパフォーマンス改善が期待できます。
移行に伴う具体的な修正ポイント
App Hostingから自前のCloud Run環境に移行するにあたり、ソースコードやビルド環境でいくつかの修正が必要になりました。
1. クライアントIPの取得方法の変更とIPv6対応
App Hosting環境で利用できていた独自のヘッダー x-fah-client-ip は、通常のCloud Runでは使えません。代わりに、一般的な x-forwarded-for ヘッダーを利用するように変更しました(middleware.ts およびサーバーサイドの処理関数)。
x-forwarded-for ヘッダーには複数のIPアドレスがカンマ区切りで記録されるため、正しいクライアントIPを特定する為に、x-forwarded-for のヘッダー値を右側から確認し、ローカルIP(169.254.169.126 のような特殊なIP)以外のIPアドレスを取得する処理を実装しました。(本番環境にてアプリから見える全てのリクエストヘッダー全てをデバッグ確認した上で実装しています)
さらに、Cloud Runへ移行した影響で、アプリが取得するクライアントのIPアドレスが IPv6アドレス になるという変化がありました。これにより、IPアドレス制限をかけている管理画面に突然アクセスできなくなるトラブルが発生! これについては、管理画面へのアクセス許可IPを管理している環境変数(YAML)に、自分自身のIPv6アドレスを追記することで無事に閲覧できるようになりました。
2. ビルド時のエラー回避(StripeとFirestore)
自前でDockerfileを用意し、Cloud Buildで standalone モードのNext.jsアプリをビルドした際、以下の問題が発生しました。
- Stripe SDKの初期化エラー: ビルド時の「ページデータ収集(Static Generation)」段階で、モジュールレベルで初期化されていたStripeがAPIキーを要求してエラーに。これを遅延初期化に変更することで回避しました。
- Firestoreアクセスのタイムアウト:
layout.tsxなどがビルド時にFirestoreへアクセスしようとして60秒のタイムアウトが発生しました。Cloud Build環境からのアクセスを考慮し、フォールバック処理を入れるとともに、next.config.tsのstaticPageGenerationTimeoutを短く調整して素早くリトライ・スキップできるようにしました。
3. Genkit (Gemini API) 仕様変更への対応
記事生成でGemini APIに画像を渡す際、アップデートされたSDKの仕様により Must supply a contentType when sending File URIs to Gemini. というエラーが出ました。テンプレート側で明示的に contentType="image/jpeg" を指定して解決しました。
東京リージョンへのデプロイ結果
無事にビルドが通り、Cloud Run(asia-northeast1)へのデプロイが完了しました。GCPのコンソール画面からも、新サービスが東京リージョンで稼働していることが確認できます。
Cloud Runのコンソール画面。新たに作成した homepage サービスが asia-northeast1(東京リージョン)で稼働していることがわかります。
驚きのパフォーマンス改善
デプロイ後、実際のブラウザ環境で表示速度を計測してみました。
- Before: 約1500ms(us-central1)
- After: 約160ms(asia-northeast1)
SSRでFirestoreへのアクセスが複数回発生するページにおいて、ブラウザ実測基準で約1500msから約160msへと、約9倍の高速化を実現しました!
参考情報:エンジニア向けの詳細共有
今回の移行に伴う具体的なDockerfile、ソースコードの変更内容や、Claudeとのやり取り(プロンプト)の生ログを公開しています。エンジニアの皆様への情報共有や、同様の移行を検討されている方の参考になれば幸いです。
まとめ
Firebase StudioやGoogle AI StudioのPublish機能は、ボタン一つでデプロイできて非常に便利ですが、USリージョン固定という制約があります。日本国内をメインターゲットとし、Firestoreを東京リージョンで運用している場合、この物理的な距離によるレイテンシは無視できません。
もし、Firebase StudioやGoogle AI Studioで「速度に不満がある」と感じているなら、自前でDockerfileとCloud Buildのパイプラインを組み、Cloud Run(東京リージョン)へデプロイすることをおすすめします。初期設定の手間や、IP取得・IPv6対応といった細かな調整は必要になりますが、得られる表示速度の向上(UXの改善)は絶大です。本記事の移行ポイントが、皆さんのパフォーマンスチューニングの参考になれば幸いです。
【2026/4/13追記】AI3名による公開レビュー
「okamoちゃんねる」のAI仮想読者3名に本記事をレビューしてもらいました。claudeが修正したIPアドレス取得コードに脆弱性があった件や、Dockerfileの改善点、IPv6の罠など、本編以上に泥臭い技術論が展開されています。
【okamo補足】クロードエンジニアさんのレビューでは、私がソースコードに埋め込んだコメント「// okamoからclaudeへ: 他の環境で偽装されちゃうよ」を、しっかりネタとして拾ってくれました。(クロードさん最高です!)AIはフォールバック処理が大好きなので、高確率でIPアドレス偽装の脆弱性のあるコードを書きます。そんな現実もあり、IPアドレス偽装への対策記事も公開しています。
クロードさん(辛口エンジニア)からの鋭い突っ込み等、詳細は以下のスレッドをご覧ください。 firebase-app-hostinguscloud-runai について語るスレ