Performance & Scalabilityシリーズの一部
完全ガイドを読むAPI パフォーマンス: レート制限、ページネーション、非同期処理
API は、ピーク負荷時に最も遅いエンドポイントと同じ速度しかありません。 最適化されていない単一のエンドポイントがデータベース接続を 5 秒間保持すると、接続プールが枯渇し、プラットフォーム全体に障害が連鎖する可能性があります。 API パフォーマンス エンジニアリングは、API を過負荷から保護する (レート制限)、大規模なデータセットを効率的に処理する (ページネーション)、高価な操作をリクエスト サイクルから外す (非同期処理) という 3 つの柱に焦点を当てています。
重要なポイント
- トークン バケットとスライディング ウィンドウは、ユースケースの 95% をカバーする 2 つのレート制限アルゴリズムです -- バースト耐性が必要か厳密な強制が必要かに基づいて選択してください
- カーソルベースのページネーションは、スキップされた行のカウントを避けるため、大規模なデータセットに対してオフセット ページネーションよりも優れたパフォーマンスを発揮します。
- ジョブ キューを使用した非同期処理により、電子メール送信、PDF 生成、Webhook 配信がリクエスト パスの外に移動されるため、P95 応答時間が短縮されます。
- Brotli による応答圧縮によりペイロード サイズが 70 ~ 85% 削減され、クライアント側のレンダリングが高速化されます。
レート制限アルゴリズム
レート制限は API を悪用から保護し、公平なリソース割り当てを保証し、トラフィック急増時のカスケード障害を防ぎます。選択したアルゴリズムによって、バーストがどのように処理されるか、および消費者にとって制限動作がどの程度予測可能かが決まります。
| アルゴリズム | バースト処理 | メモリ使用量 | 精度 | 最適な用途 |
|---|---|---|---|---|
| 固定ウィンドウ | ウィンドウ境界で 2x バーストを許可 | 非常に低い | 低い | 単純な使用例、内部 API |
| スライディングウィンドウログ | バーストなし、正確 | 高 (タイムスタンプを保存) | 非常に高い | 金融 API、厳格なコンプライアンス |
| 引き違い窓カウンター | 最小限の境界バースト | 低い | 高 | 汎用パブリック API |
| トークンバケット | 制御されたバーストを許可します。低い | 中程度 | 自然なバースト パターンを持つ API | |
| 漏れやすいバケツ | すべての交通をスムーズにします | 低い | 高 | 安定したスループットを必要とする API |
トークンバケット
トークン バケット アルゴリズムは、ほとんどの API にとって最も実用的な選択肢です。バケットには、最大容量までトークンが保持されます。トークンは固定レート (補充レート) で追加されます。各リクエストは 1 つのトークンを消費します。バケットが空の場合、リクエストは拒否されるかキューに入れられます。
トークン バケットの主な利点は、バースト耐性です。クライアントがしばらくリクエストを行わなかった場合、バケットはいっぱいになり、バケットの容量まで大量のリクエストを行うことができます。これは自然な使用パターンと一致します。ダッシュボードをロードするクライアントは、20 件のリクエストを立て続けに作成し、その後 30 秒間何も行わない可能性があります。
eCommerce API の設定例:
- バケットサイズ: 100トークン
- 補充速度: 1 秒あたり 10 トークン
- これにより、1 秒あたり 10 リクエストを長期間維持しながら、最大 100 リクエストのバーストが可能になります
引き違い窓カウンター
スライディング ウィンドウ カウンタは、スライディング ウィンドウ ログの精度と固定ウィンドウのメモリ効率を組み合わせています。現在および前のウィンドウのカウンターを維持し、リクエストが現在のウィンドウにどれだけ入っているかに基づいて重み付けされたカウントを計算します。
45 秒以内に評価される 60 秒のウィンドウの場合、有効なカウントは (前のウィンドウ カウント * 0.25) + (現在のウィンドウ カウント) となります。これにより、個々のリクエストのタイムスタンプを保存することなく、固定ウィンドウの境界バーストの問題が解消されます。
Redis を使用した実装
Redis は、TTL によるアトミックな増分操作を提供するため、分散レート制限の標準バッキング ストアです。固定ウィンドウの場合は EXPIRE を指定した INCR を使用し、スライディング ウィンドウの場合は ZADD および ZRANGEBYSCORE を使用したソート セットを使用します。トークン バケットの場合、Redis Lua スクリプトはアトミックなチェックとデクリメントの操作を提供します。
レート制限ヘッダー は、API コンシューマーに制限を伝えます。
X-RateLimit-Limit-- ウィンドウ内で許可される最大リクエスト数X-RateLimit-Remaining-- 現在のウィンドウに残っているリクエストX-RateLimit-Reset-- ウィンドウがリセットされたときの Unix タイムスタンプRetry-After-- クライアントが再試行するまでの秒数 (429 応答時)
ページネーション戦略
すべてのリストのエンドポイントはページ分割する必要があります。無制限の結果セットを返すと、帯域幅が無駄になり、データベースに負担がかかり、データの増大に伴ってタイムアウト エラーが発生する危険性があります。
オフセットページネーション
オフセット ページネーションでは、LIMIT および OFFSET SQL 句を使用します。クライアントは ?page=3&limit=20 をリクエストし、サーバーは OFFSET 40 LIMIT 20 に変換します。
利点:
- 実装と理解が簡単
- クライアントは任意のページに直接ジャンプできます
- 合計カウントにより、「Y ページの X」UI が有効になります
短所:
- オフセットが大きいとパフォーマンスが低下します --
OFFSET 1000000は結果を返す前に 1,000,000 行をスキャンします - ページ間でデータが変更されると結果が不一致になる (新しいデータが挿入または削除されると行が移動する)
- 合計カウント クエリ (COUNT(*)) は、大きなテーブルではコストがかかる場合があります
カーソルベースのページネーション
カーソルベースのページネーションでは、不透明なカーソル (通常はエンコードされた主キーまたはタイムスタンプ) を使用して、結果セット内の位置をマークします。クライアントは ?cursor=abc123&limit=20 をリクエストし、サーバーはカーソルを WHERE 句として使用します: WHERE id > decoded(abc123) LIMIT 20。
利点:
- データセット内の位置に関係なく一貫したパフォーマンス -- オフセット スキャンなし
- ページ間でデータが変更された場合でも安定した結果
- 無限スクロールとリアルタイム フィードに自然にフィット
短所:
- 任意のページにジャンプすることはできません(「50ページへ移動」はありません)
- 特に複数列の並べ替え順序の場合、実装がより複雑になります
- 必要に応じて合計数を別途提供する必要があります
どのページネーションを使用するか
| シナリオ | 推薦 | 理由 |
|---|---|---|
| ページ番号付きの管理データ テーブル | オフセット | ユーザーはページ ナビゲーションを期待しています |
| モバイル無限スクロール | カーソル | あらゆる深さでのパフォーマンス |
| 統合によって消費される API | カーソル | バッチ処理のための安定したページネーション |
| 小規模なデータセット (10,000 行未満) | どちらか | パフォーマンスの違いは無視できます |
| 大規模なデータセット (100,000 行以上) | カーソル | オフセットが使用できないほど遅くなる |
| リアルタイム フィード (チャット、通知) | カーソル | 新しいデータが到着したときの一貫性 |
ページネーション応答フォーマット
適切に設計されたページネーション応答には、クライアントがナビゲートする必要があるメタデータが含まれています。
{
"data": [],
"pagination": {
"total": 15432,
"limit": 20,
"hasMore": true,
"nextCursor": "eyJpZCI6MTAwfQ=="
}
}
ジョブキューによる非同期処理
同期 API エンドポイントは 200 ミリ秒以内に応答を返す必要があります。時間のかかる操作 (電子メールの送信、PDF の生成、画像の処理、外部 API の呼び出し、レポートの実行) はすべて、バックグラウンド ジョブ キューに移動する必要があります。
ジョブキューパターン
- API エンドポイントはリクエストを検証し、ジョブ レコードを作成します。
- ジョブはキューに配置されます (Redis、RabbitMQ、SQS)
- API はすぐに 202 Accepted 応答とジョブ ID を返します。
- ワーカー プロセスがジョブを取得し、非同期で実行します。
- クライアントはジョブのステータスをポーリングするか、完了時に Webhook コールバックを受け取ります。
一般的な非同期の使用例
電子メール送信 -- SMTP 操作には、プロバイダーによって異なりますが 500 ミリ秒から 3 秒かかります。電子メールをキューに入れると、API の応答時間が短縮され、ユーザーをブロックすることなく一時的なエラーに対するロジックの再試行が可能になります。
PDF の生成 -- 請求書、レポート、またはエクスポート ファイルの生成は、CPU とメモリを大量に消費します。これらを専用ワーカーで実行すると、API リクエスト処理によるリソースの競合が防止されます。
Webhook の配信 -- 発信 Webhook は、サードパーティのサーバーの可用性に依存します。指数バックオフ再試行 (1 秒、2 秒、4 秒、8 秒、最大 5 分) を使用して Webhook 配信をキューに入れ、システムをブロックすることなく一時的な障害を処理します。
データのインポートとエクスポート -- 100,000 行の CSV アップロードの処理は、リクエスト サイクル内で決して発生すべきではありません。アップロードを受け入れ、ジョブ ID を返し、バッチで行を処理します。
キューの選択
| キューテクノロジー | 最適な用途 | 考慮事項 |
|---|---|---|
| BullMQ (Redis 支援) | Node.js アプリケーション、NestJS 統合 | 優れた開発者エクスペリエンス、内蔵ダッシュボード |
| ラビットMQ | 多言語システム、複雑なルーティング | 成熟した、メッセージ確認パターンをサポート |
| AWS SQS | サーバーレス、マネージド インフラストラクチャ | サーバー管理なし、メッセージごとの支払い |
| カフカ | イベントストリーミング、高スループット | 単純なジョブ キューには過剰ですが、イベント ソーシングには優れています |
応答の最適化
アプリケーション ロジックを超えて、応答自体のサイズと配信速度を最適化できます。
圧縮
応答圧縮を有効にして、ネットワーク上のペイロード サイズを削減します。最新の圧縮アルゴリズムにより、テキストベースのペイロード (JSON、HTML、CSS、JavaScript) が大幅に削減されます。
| アルゴリズム | 圧縮率 | CPU コスト | ブラウザのサポート |
|---|---|---|---|
| gzip | 60 ~ 75% 削減 | 低い | ユニバーサル |
| ブロトリ | 70-85% 削減 | 中程度 | 最新のすべてのブラウザ |
| zstd | 70-85% 削減 | 低い | 新興 (まだ普遍的ではない) |
静的アセット (ビルド時に事前圧縮) には Brotli を使用し、動的応答のフォールバックとして gzip を使用します。 NestJS では、圧縮ミドルウェアがこれを自動的に処理しますが、運用環境では、アプリケーション サーバーから CPU をオフロードするために Nginx に圧縮を処理させます。
フィールドの選択
API コンシューマーが必要なフィールドのみをリクエストできるようにします。 GraphQL はこれを本質的に行いますが、REST API は ?fields=id,name,price クエリ パラメーターを使用したフィールド選択をサポートできます。これによりペイロード サイズが削減され、必要な列のみを選択することでデータベース クエリを最適化できます。
応答キャッシュヘッダー
API 応答に適切な Cache-Control ヘッダーを設定します。パブリック リストのエンドポイント (製品、カテゴリ) は、Cache-Control: public, max-age=300 を使用して 5 分間キャッシュできます。認証されたエンドポイントは Cache-Control: private, no-cache を使用して CDN キャッシュを防止し、再検証によるブラウザー キャッシュを許可する必要があります。
キャッシュ戦略の詳細については、Redis、CDN、および HTTP キャッシュ に関する詳細ガイドを参照してください。
接続管理
データベースと HTTP 接続は有限のリソースであり、負荷がかかっている状態では慎重に管理する必要があります。
データベース接続プーリング
接続プールは、再利用可能なデータベース接続のセットを維持します。プールを使用しない場合、各 API リクエストは新しいデータベース接続を開き (50 ~ 100 ミリ秒のオーバーヘッド)、応答後に接続を閉じます。プーリングを使用すると、リクエストはプールから接続を借用し、完了すると接続を返します。
プール サイズの計算式: 接続数 = (core_count * 2) +Effective_spindle_count。 SSD ストレージを備えた 4 コア サーバーの場合、アプリケーション インスタンスあたり 10 ~ 20 の接続が適切な開始点です。プールの使用率を監視します。定期的に 80% を超える場合は、プールのサイズを増やすか、クエリの期間を最適化します。
HTTP キープアライブ
アップストリーム サービス (データベース、Redis、外部 API) への接続に対して HTTP キープアライブを有効にします。これにより、リクエストごとに新しい接続を確立するのではなく、TCP 接続が再利用され、TCP ハンドシェイクと TLS ネゴシエーションのオーバーヘッド (新しい接続ごとに 50 ~ 200 ミリ秒) が排除されます。
よくある質問
パブリック API にはどのようなレート制限を設定する必要がありますか?
控えめな制限から始めて、正当な使用パターンに基づいて調整します。一般的な開始点は、認証されたユーザーの場合は 1 分あたり 100 リクエスト、匿名ユーザーの場合は 1 分あたり 20 リクエストです。 429 応答率を監視します -- 正当なユーザーが頻繁に制限に達する場合は、応答率を上げます。プレミアム API 層に対してより高い制限を提供します。
ページ間でデータが変更された場合、ページネーションをどのように処理すればよいですか?
カーソルベースのページネーションは、並べ替えられたデータ内の特定の位置にアンカーされるため、これを自然に処理します。オフセット ページネーションを使用すると、ドキュメントの結果がページ間で移動する可能性があります。重要な使用例 (財務レポート、データ エクスポート) の場合は、ページ分割の開始時にデータのスナップショットを作成し、スナップショット上でページ分割します。
パフォーマンスのために REST または GraphQL を使用する必要がありますか?
シンプルで明確に定義されたエンドポイントの場合、フィールド選択と適切なキャッシュを備えた REST の方が高速です。 GraphQL は、複雑なデータ要件に対するオーバーフェッチとアンダーフェッチを排除しますが、クエリ解析のオーバーヘッドが追加され、HTTP キャッシュが難しくなります。キャッシュが必要なパブリック API には REST を使用し、複雑なフロントエンド データ要件に対応する内部 API には GraphQL を使用します。
本番環境で API のパフォーマンスを監視するにはどうすればよいですか?
エンドポイントごとに P50、P95、および P99 の応答時間を追跡します。 SLO に違反する P95 についてアラートを設定します (通常は 200 ~ 500 ミリ秒)。分散トレースを使用して、データベース、キャッシュ、外部サービス、アプリケーション ロジックに費やされた時間を分析します。詳細な設定については、監視と可観測性 に関するガイドを参照してください。
次は何ですか
まず、API エンドポイントでページネーションの欠落、レート制限のない保護されていないパブリック エンドポイント、および非同期である必要がある同期操作を監査します。これら 3 つの変更により、通常、P95 の応答時間が 50 ~ 70% 短縮され、最も一般的な運用インシデントが防止されます。
パフォーマンス エンジニアリングの完全な観点については、[ビジネス プラットフォームのスケーリング] (/blog/scaling-business-platform-performance) に関する柱ガイドを参照してください。 API を強化するデータベース層については、クエリ最適化ガイド をご覧ください。
ECOSIRE は、Odoo ERP およびカスタム アーキテクチャ上のビジネス プラットフォーム用の高性能 API を構築します。 API パフォーマンスのレビューについては、お問い合わせ してください。
ECOSIRE によって発行 — Odoo ERP、Shopify eCommerce、OpenClaw AI にわたる AI を活用したソリューションで企業のスケールアップを支援します。
執筆者
ECOSIRE TeamTechnical Writing
The ECOSIRE technical writing team covers Odoo ERP, Shopify eCommerce, AI agents, Power BI analytics, GoHighLevel automation, and enterprise software best practices. Our guides help businesses make informed technology decisions.
関連記事
Hepsiburada API と Odoo の統合: 完全なセットアップ ガイド
API を介して Hepsiburada と Odoo ERP を統合するための完全なガイド。トルコの信頼できる市場で注文、在庫、発送を自動化します。
Shopify Integration Hub: 2026 年に Shopify を任意のシステムに接続する方法
Shopify 統合の完全ガイド: API、Webhook、ミドルウェア、iPaaS メソッド。 Shopify を ERP、会計、CRM、マーケットプレイス、POS システムに接続します。
API レート制限: パターンとベスト プラクティス
トークン バケット、スライディング ウィンドウ、固定カウンター パターンによるマスター API レート制限。 NestJS スロットラー、Redis、実際の構成例を使用してバックエンドを保護します。
Performance & Scalabilityのその他の記事
Webhook のデバッグと監視: 完全なトラブルシューティング ガイド
障害パターン、デバッグ ツール、再試行戦略、監視ダッシュボード、セキュリティのベスト プラクティスを網羅したこの完全なガイドを利用して、Webhook デバッグをマスターしてください。
k6 負荷テスト: 起動前に API のストレス テストを行う
Node.js API の k6 負荷テストをマスターします。仮想ユーザーの増加、しきい値、シナリオ、HTTP/2、WebSocket テスト、Grafana ダッシュボード、CI 統合パターンをカバーします。
Nginx 実稼働構成: SSL、キャッシュ、およびセキュリティ
Nginx 実稼働構成ガイド: SSL 終端、HTTP/2、キャッシュヘッダー、セキュリティヘッダー、レート制限、リバースプロキシセットアップ、Cloudflare 統合パターン。
Odoo パフォーマンス チューニング: PostgreSQL とサーバーの最適化
Odoo 19 のパフォーマンス チューニングに関する専門ガイド。 PostgreSQL の構成、インデックス作成、クエリの最適化、Nginx キャッシュ、エンタープライズ展開のためのサーバーのサイジングについて説明します。
Odoo 対 Acumatica: 成長するビジネスのためのクラウド ERP
2026 年の Odoo と Acumatica の比較: 独自の価格モデル、スケーラビリティ、製造の深さ、成長軌道に適合するクラウド ERP はどれですか。
本番環境での AI エージェントのテストと監視
実稼働環境で AI エージェントをテストおよび監視するための完全なガイド。 OpenClaw 導入の評価フレームワーク、可観測性、ドリフト検出、インシデント対応について説明します。