Agent Skills by ALSEL
汎用DevOps・インフラ⭐ リポ 38品質スコア 80/100

algolia-cost-tuning

Algoliaのコスト最適化:検索リクエストとレコード課金の違いを理解し、バッチ処理とキャッシングで操作を削減し、Analytics APIで利用状況を監視します。 トリガーキーワード:「algolia cost」「algolia billing」「reduce algolia costs」「algolia pricing」「algolia expensive」「algolia budget」

description の原文を見る

Optimize Algolia costs: understand search request vs record pricing, reduce operations with batching and caching, monitor usage via Analytics API. Trigger: "algolia cost", "algolia billing", "reduce algolia costs", "algolia pricing", "algolia expensive", "algolia budget".

SKILL.md 本文

Algolia コスト最適化

概要

Algoliaの価格設定は検索リクエストレコードに基づいています。検索リクエストは1つのAPI呼び出しです(search({ requests: [...] })で複数のクエリが含まれることもあります)。レコードはレプリカを含むすべてのインデックスで集計されます。

価格体系 (2025)

プラン含まれるレコード検索リクエスト追加費用
Build (無料)100万レコード月1万リクエストなし
Grow10万無料、その後$0.40/1千月1万無料、その後$0.50/1千従量課金
Grow Plus10万無料、その後$0.40/1千月1万無料、その後$1.75/1千+ AI機能
Premiumカスタムカスタムボリュームディスカウント

レコードとして計算される対象

  • すべてのインデックス内の各オブジェクト = 1レコード
  • 標準レプリカはレコードを複製します(カウント数が増加)
  • 仮想レプリカはレコードを共有します(追加コストなし)
  • シノニムとルールはレコードとしてカウントされません

検索リクエストとして計算される対象

  • searchSingleIndex() = 1リクエスト
  • search({ requests: [q1, q2, q3] }) = 1リクエスト (マルチクエリ)
  • browse() = ページあたり1リクエスト
  • saveObjects() = 検索リクエストではありません (インデックス作成操作は無料)

手順

ステップ1: 現在の利用状況を監査

import { algoliasearch } from 'algoliasearch';

const client = algoliasearch(process.env.ALGOLIA_APP_ID!, process.env.ALGOLIA_ADMIN_KEY!);

// すべてのインデックスのレコード総数を確認
const { items } = await client.listIndices();
let totalRecords = 0;
let replicaRecords = 0;

items.forEach(idx => {
  const records = idx.entries || 0;
  console.log(`${idx.name}: ${records.toLocaleString()} records, ${(idx.dataSize || 0 / 1024).toFixed(0)}KB`);
  if (idx.name.includes('_replica') || idx.primary) {
    replicaRecords += records;
  }
  totalRecords += records;
});

console.log(`\nTotal: ${totalRecords.toLocaleString()} records (${replicaRecords.toLocaleString()} in replicas)`);

ステップ2: 標準レプリカを仮想レプリカに置き換える

// 標準レプリカ: すべてのレコードを複製 (コスト2倍)
// 仮想レプリカ: プライマリインデックスと共有 (追加コストなし)

// 変更前: 3つの標準レプリカ = レコードカウント4倍
await client.setSettings({
  indexName: 'products',
  indexSettings: {
    replicas: [
      // 'products_price_asc',      // 標準: レコードコスト発生
      // 'products_price_desc',     // 標準: レコードコスト発生
      'virtual(products_price_asc)',  // 仮想: 無料
      'virtual(products_price_desc)', // 仮想: 無料
    ],
  },
});

// 仮想レプリカの制限: ランキングとcustomRankingのカスタマイズのみ可能
// searchableAttributesやattributesForFacetingを別に変更する必要がある場合は標準レプリカを使用

ステップ3: マルチクエリを使用してリクエスト数を削減

// 悪い例: 3つの別々のリクエスト = 3つの検索操作に課金
const results1 = await client.searchSingleIndex({ indexName: 'products', searchParams: { query: 'laptop' } });
const results2 = await client.searchSingleIndex({ indexName: 'articles', searchParams: { query: 'laptop' } });
const results3 = await client.searchSingleIndex({ indexName: 'faq', searchParams: { query: 'laptop' } });

// 良い例: 1つのマルチクエリリクエスト = 1つの検索操作に課金
const { results } = await client.search({
  requests: [
    { indexName: 'products', query: 'laptop', hitsPerPage: 5 },
    { indexName: 'articles', query: 'laptop', hitsPerPage: 3 },
    { indexName: 'faq', query: 'laptop', hitsPerPage: 3 },
  ],
});

ステップ4: 頻繁な検索をキャッシュ

import { LRUCache } from 'lru-cache';

// 人気のある検索をキャッシュ — Algoliaの独自CDNキャッシュは制限あり
const searchCache = new LRUCache<string, any>({
  max: 1000,
  ttl: 5 * 60 * 1000, // 製品検索用5分
});

async function cachedSearch(query: string, filters?: string) {
  const key = JSON.stringify({ query, filters });
  const cached = searchCache.get(key);
  if (cached) {
    console.log('Cache hit — saved 1 search request');
    return cached;
  }
  const result = await client.searchSingleIndex({
    indexName: 'products',
    searchParams: { query, filters },
  });
  searchCache.set(key, result);
  return result;
}

ステップ5: 未使用のインデックスを削除

// テスト/開発用インデックスを監査してクリーンアップ
const { items } = await client.listIndices();
const devIndices = items.filter(i =>
  i.name.startsWith('test_') ||
  i.name.startsWith('dev_') ||
  i.name.startsWith('ci_')
);

for (const idx of devIndices) {
  console.log(`Deleting unused index: ${idx.name} (${idx.entries} records)`);
  await client.deleteIndex({ indexName: idx.name });
}

ステップ6: Analytics APIを使用して利用状況を監視

// 検索ボリュームのトレンドを追跡
const { count: searchCount } = await client.getSearchesCount({
  index: 'products',
  startDate: '2025-01-01',
  endDate: '2025-01-31',
});
console.log(`Search requests this month: ${searchCount.toLocaleString()}`);

// 結果なしのクエリを特定 (ユーザーが再試行する無駄な検索)
const { searches } = await client.getSearchesNoResults({
  index: 'products',
  startDate: '2025-01-01',
  endDate: '2025-01-31',
});
console.log('Top no-result searches (fix these to reduce retries):');
searches.slice(0, 10).forEach(s => console.log(`  "${s.search}" — ${s.count} times`));

コスト削減の概要

戦略削減効果実装難度
仮想レプリカレコードコスト50-75%削減
マルチクエリ検索リクエスト60-80%削減
クライアント側キャッシングリクエスト30-50%削減
未使用インデックスの削除可変
結果なしクエリの修正 (シノニム)再試行10-20%削減
レコードサイズを削減間接的 (高速化=安価化)

エラーハンドリング

問題原因解決策
予期しない請求額の増加キャッシュされていないボット トラフィックレート制限またはキャッシュ層を追加
予想より高いレコード数標準レプリカ仮想レプリカに切り替え
予算を超える検索リクエストキャッシングなしAPI層にLRUキャッシュを追加
Analytics APIが空を返す日付範囲またはリージョンが誤りregionパラメータがアプリに一致しているか確認

リソース

次のステップ

アーキテクチャパターンについては、algolia-reference-architectureを参照してください。

ライセンス: MIT(寛容ライセンスのため全文を引用しています) · 原本リポジトリ

詳細情報

作者
ComeOnOliver
リポジトリ
ComeOnOliver/skillshub
ライセンス
MIT
最終更新
2026/5/11

Source: https://github.com/ComeOnOliver/skillshub / ライセンス: MIT

本サイトは GitHub 上で公開されているオープンソースの SKILL.md ファイルをクロール・インデックス化したものです。 各スキルの著作権は原作者に帰属します。掲載に問題がある場合は info@alsel.co.jp または /takedown フォームよりご連絡ください。
原作者: ComeOnOliver · ComeOnOliver/skillshub · ライセンス: MIT