Firebase + Algoliaの限界:個人開発でAWS移行した2理由と体験談

2025.09.22個人開発日誌https://img.morisakiblog.com/posts/firebase-algolia-to-aws-migration/7137fa46-8cf2-4d9b-b1a1-d1678766662f.jpg
Firebase + Algoliaの限界:個人開発でAWS移行した2理由と体験談

クイズ共有アプリを個人開発してGoogle Playでリリースしている者です。最初はFirebase + Algoliaの組み合わせで快適に開発していましたが、機能を拡張していく中で「なんか辛いな…」と感じることが増えてきました。

今回は実際に感じた問題点と、AWS移行を決断した理由について、実体験を交えて書いてみます。

📱 対象アプリ

GitHub: share_quiz

最初は快適だったFirebase

個人開発を始めた当初、Firebaseは本当に素晴らしいサービスでした。

// 認証も簡単
await FirebaseAuth.instance.signInWithGoogle();

// データベースも直感的
await FirebaseFirestore.instance
  .collection('quiz')
  .add(quizData);

セットアップが簡単で、インフラを意識せずに開発に集中できる。個人開発者にとって理想的な環境でした。

特に以下の機能は本当に素晴らしく、開発初期は「Firebase最高!」と思っていました。

  • リアルタイム更新: 他のユーザーの投稿が即座に反映
  • 簡単な認証: Google/Apple/メール認証が数行で実装
  • 自動スケーリング: インフラ管理不要
  • 豊富なSDK: Flutter/React/iOS/Android対応
// リアルタイムでデータが同期される
FirebaseFirestore.instance
  .collection('quiz')
  .snapshots()
  .listen((snapshot) {
    // 他のユーザーが投稿したクイズが即座に反映
    updateUI(snapshot.docs);
  });

このリアルタイム機能により、ユーザー同士のインタラクションが活発になり、アプリの魅力が大幅に向上しました。

問題1: Firestoreの限界に直面

アプリの機能を拡張していく中で、Firestoreの制約が徐々に見えてきました。

複雑な検索ができない

ユーザーから「タイトルに”歴史”を含み、難易度が中級以上で、作成日が1週間以内のクイズを検索したい」という要望が来ました。

// やりたいこと(SQLなら簡単)
SELECT * FROM quiz 
WHERE title LIKE '%歴史%' 
  AND difficulty >= 'intermediate'
  AND created_at >= DATE_SUB(NOW(), INTERVAL 1 WEEK);

// Firestoreでは...無理!
// 複数の不等号条件は使えない
// LIKE検索もできない

結果的に、複数のクエリに分割してアプリ側で結合する必要がありました。

インデックスの事前登録が必要

さらに、Firestoreで複数フィールドでクエリを実行するためには、Composite Index(複合インデックス)を事前に登録しなければなりません。

// このクエリを実行するためには...
FirebaseFirestore.instance
  .collection('quiz')
  .where('category', isEqualTo: 'history')
  .where('difficulty', isEqualTo: 'intermediate')
  .orderBy('createdAt', descending: true)
  .get();

// Firebase Consoleで手動でインデックス作成が必要!
// category + difficulty + createdAt の組み合わせ

😅 開発中のストレス

「クエリを追加するたびにFirebase Consoleでインデックス作成…」 「インデックス作成に5-10分かかるし、忘れることも…」

ローカル開発ではエラーが出て、本番では動かないということもありました。

JOIN的な操作ができない

// やりたいこと:クイズと作成者情報を一緒に取得
// RDBなら簡単なJOIN

// Firestoreでは仕方なく複数回取得
final quiz = await getQuiz(quizId);
final creator = await getUser(quiz.creatorId);  // 別クエリ

// N+1問題が発生しやすい

集計クエリができない

// やりたいこと:カテゴリ別のクイズ数を表示
// COUNT()が使えない!

// 全件取得してアプリ側で集計...
final allQuiz = await collection.get();
final categoryCount = {};
for (final doc in allQuiz.docs) {
  final category = doc.data()['category'];
  categoryCount[category] = (categoryCount[category] ?? 0) + 1;
}

💡 気づいた瞬間

「あれ?これって普通のデータベースなら簡単にできることなのに…」

NoSQL固有の問題

実はこれらの問題はFirestore固有ではなく、NoSQL全般の特徴です。MongoDB、DynamoDB、Cassandraなど、どのNoSQLでも同様の制約があります。

  • スケーラビリティ重視でクエリ機能を犠牲
  • 非正規化前提の設計思想
  • 結合処理はアプリケーション側で実装

NoSQLは「大量データを高速処理」するために生まれた技術なので、複雑なクエリができないのは仕様なんです。ただし、インデックスの事前登録は開発効率を大きく下げる要因でした。

Firebase Data Connectについて

※ 2024年にFirebase Data Connect(PostgreSQLベース)がリリースされましたが、現在はPreview版のため本番利用は推奨されません。正式版がリリースされれば、Firebaseでも複雑なクエリが可能になる予定です。

問題2: Algoliaの運用が辛い

Firestoreの検索機能の弱さを補うため、Algoliaを導入しました。検索機能自体は素晴らしいのですが、運用面で問題が…

手動デプロイ地獄

# staging環境の設定
algolia indices export quiz_staging --output staging.json

# production環境の設定
algolia indices export quiz_production --output prod.json

# 設定が微妙に違う...どっちが正しい?

環境管理の複雑さ

ダッシュボードで手動設定する項目が多すぎて、環境間の同期が困難でした。

  • searchableAttributes: 手動設定
  • ranking: 手動設定
  • synonyms: 手動追加
  • stop words: 手動追加

staging → production への反映が全て手作業になってしまいました。

バージョン管理できない

😱 実際にあった問題

「昨日まで動いてた検索が急に変になった」 原因:誰かがダッシュボードで設定変更 解決:???(履歴が分からない)

GitHub Actionsでの自動化も困難

# 頑張って自動化しようとしても...
- name: Deploy Algolia settings
  run: |
    algolia indices import quiz --input settings.json
    # 部分的な失敗を見逃しやすい
    # ロールバックが困難
    # 設定の検証が別途必要

技術的には可能ですが、工数対効果が悪すぎました。その時間を機能開発に使いたい…

予想外のコスト増加

💸 Algoliaの料金体系

– 無料枠: 月10,000検索まで – その後: 1,000検索あたり$0.50 – ユーザーが増えると一気に高額に…

最初は無料で使えるので気軽に導入しましたが、ユーザーが増えるにつれて検索回数が急増。月額料金が予想以上に高くなってしまいました。

AWS移行の決断

これらの問題を解決するため、AWS移行を決断しました。

移行後の構成

「NoSQLの問題って言ったのに、またDynamoDB(NoSQL)使うの?」と思われるかもしれませんが、AWSではFirestoreの問題を解決できる仕組みがあります。

// CDKでインフラをコード管理
const dynamoTable = new Table(this, 'QuizTable', {
  partitionKey: { name: 'id', type: AttributeType.STRING },
  billingMode: BillingMode.PAY_PER_REQUEST,
  // GSIで柔軟なインデックス管理
  globalSecondaryIndexes: [{
    indexName: 'CategoryIndex',
    partitionKey: { name: 'category', type: AttributeType.STRING },
    sortKey: { name: 'createdAt', type: AttributeType.STRING },
  }]
});

// 検索はOpenSearchに任せる
const searchDomain = new Domain(this, 'SearchDomain', {
  version: EngineVersion.OPENSEARCH_1_3,
  capacity: { dataNodes: 2 },
});

なぜDynamoDB + OpenSearchを選んだのか

「RDSの方が簡単じゃない?」と思われるかもしれませんが、以下の理由でDynamoDB + OpenSearchを選択しました。

DynamoDB + OpenSearchの利点RDSと比較したデメリット
役割分担: シンプルクエリはDynamoDB、複雑検索はOpenSearch複雑性: 2つのサービスを管理
コスト効率: 必要な時だけOpenSearchを使用学習コスト: DynamoDBの設計思想を理解する必要
パフォーマンス: 各サービスが得意分野に特化データ同期: DynamoDB→OpenSearchの同期処理
スケーラビリティ: 将来的な成長に対応

Firestoreとの決定的な違い

🔄 最大の違い:インフラのコード管理

Firestore: コンソールで手動設定 → 環境差異、バージョン管理不可 AWS: CDKでコード管理 → Git管理、環境一致、自動デプロイ

具体的な解決内容

  • インデックス管理: GSI/LSIをCDKで事前定義、手動作成不要
  • 複雑検索: OpenSearchで全文検索、ファセット検索が可能
  • 環境管理: staging/productionが同一コードで管理
  • コスト予測: AWS料金計算機で事前計算可能
  • バージョン管理: インフラ変更もGitで追跡
// インデックスもコードで管理
const categoryIndex = {
  indexName: 'CategoryDifficultyIndex',
  partitionKey: { name: 'category', type: AttributeType.STRING },
  sortKey: { name: 'difficulty', type: AttributeType.STRING },
};

// 環境別デプロイ
cdk deploy QuizApp-Staging
cdk deploy QuizApp-Production  // 同一構成でデプロイ

移行時のコスト考慮

ただし、AWSも決して安くはありません。OpenSearchは最低でも月額$20-30程度かかります。

⚠️ 重要な注意点

Firebase + Algoliaで月額$50だったものが、AWSで月額$80になることもあります。 しかし、機能の柔軟性とコストの予測可能性を考えると、本格的なビジネス利用では価値があります。

RDBという選択肢

AWSではRDS(PostgreSQL/MySQL)を使う選択肢もあります。

// RDS PostgreSQL
const database = new DatabaseInstance(this, 'QuizDB', {
  engine: DatabaseInstanceEngine.postgres({
    version: PostgresEngineVersion.VER_15_3,
  }),
  instanceType: InstanceType.of(InstanceClass.T3, InstanceSize.MICRO),
});
RDBの利点RDBの欠点
複雑なクエリが自由自在コストが高い(月額$20-50)
JOINや集計が簡単スケーラビリティに限界
データ整合性が保証レスポンス速度でNoSQLに劣る

個人開発ならRDSも十分選択肢になります。特に複雑なクエリが多い場合は、NoSQL + 検索サービスより安上がりかもしれません。

いつFirebaseを使うべきか(独断と偏見)

これまでの経験を踏まえて、どんな時にFirebaseを選ぶべきか、逆にいつ他の選択肢を検討すべきかをまとめてみました。あくまで個人的な見解ですが、参考になれば幸いです。

✅ Firebaseが向いてるケース❌ Firebaseが辛くなるケース
超短期プロトタイプ(1-3ヶ月)複雑な検索が必要
個人開発・趣味プロジェクトデータ分析・集計が重要
シンプルなデータ構造チーム開発(4人以上)
学習・ポートフォリオ目的本格的なビジネス利用

移行を検討するタイミング

  • 「あれ?これFirebaseで実現できる?」と思った時
  • 「なんでこんなに複雑になってるんだ?」と感じた時
  • 「月額料金が読めない…」と不安になった時

💡 個人的な結論

– プロトタイプ・学習: Firebase – 本格ビジネス(複雑クエリ必要): AWS RDS – 大規模・高速処理重視: AWS NoSQL + OpenSearch

最初の選択が後々の開発効率を大きく左右します。

まとめ

Firebaseは素晴らしいサービスですが、適材適所が重要です。

  • Firestoreの制約は想像以上に厳しい
  • Algoliaの運用は個人開発には重すぎる
  • 移行コストを考えると、最初の選択が重要

これから個人開発を始める方の参考になれば幸いです。

追記:その後、実際にAWS(DynamoDB + CDK)でバックエンドを作ってみたら、今度はDynamoDBで地獄を見ました。移行後の現実はこちらに書いています。

DynamoDBは地雷原だった|Firebase→AWS移行の理想と現実
DynamoDBは地雷原だった|Firebase→AWS移行の理想と現実
Firebase→AWS移行でDynamoDBを選んだ個人開発者の体験談。GSI変更は1回1デプロイ制約で10回デプロイ、FilterExpressionはlimit後に動く罠、シングルテーブル設計の落とし穴を正直に書きます。
morisakiblog.com

このバックエンドを使ったクイズSNSアプリは、最終的にApp Storeにリリースできました。開発の全記録はこちらです。

気力ゼロから1ヶ月でApp Storeリリース|AI×個人開発の全記録
気力ゼロから1ヶ月でApp Storeリリース|AI×個人開発の全記録
気力ゼロのフリーランスエンジニアがAIをフル活用して約1ヶ月でクイズSNSアプリをApp Storeにリリース。Claude Code、Figma Make、Notion MCPの活用法と各フェーズの所要時間、AIの理想と現実を正直に書きます。
morisakiblog.com

この記事は実際の開発体験を基に書いています。プロジェクトの要件や規模によって最適解は変わるので、あくまで一つの事例として参考にしてください。