p95レイテンシを下げる既存プロダクト改善入門
「ダッシュボードの平均レスポンスタイムは300msで問題ないはずなのに、一部の顧客から『たまに固まる』というクレームが来る」——この手の相談は、パフォーマンス改善の依頼の中でも特に判断を誤りやすいパターンです。平均だけを見ていると「問題なし」に見えてしまうからです。
原因は単純で、平均は「遅い一部」を「速い大多数」が薄めて隠してしまう指標だからです。この記事では、なぜ平均でなくp95・p99のようなパーセンタイルを見るべきか、テールレイテンシ(裾の遅いリクエスト)が発生する典型原因、計測の仕方、そして改善の優先順位づけを整理します。
なぜ平均でなくp95/p99を見るべきか
平均レスポンスタイムは、1万リクエストのうち9900件が100msで返り、100件が5秒かかっていても、平均は約150msにしかなりません。この100件(全体の1%)を見逃したまま「平均は速い」と報告してしまうのが、平均値の危険なところです。
- p95: リクエストの95%がこの時間以内に返っている、という値。残り5%は「p95より遅い」ことを意味する
- p99: 上位1%の遅いリクエストを表す。ECサイトやSaaSでは、この1%が実は最も高額な顧客・最もデータ量が多い顧客であることが多く、ビジネスインパクトが大きい
- 平均が動かないのにp95/p99だけ悪化する現象がある。これは特定条件下でのみ発生する局所的な問題で、全体のトラフィックからは見えにくい
目安として、toBのSaaS管理画面であれば「p95が1秒以内、p99が3秒以内」を一つの健全ラインとして置くことが多いです(業務内容によって許容値は変わります)。逆に平均が500ms前後でも、p99が10秒を超えているなら、体感クレームが出て当然の状態です。「遅いと言われているのに平均が正常」という報告は、パーセンタイルを見ていないサインとして扱ってください。
テールレイテンシが発生する典型原因
平均には現れず、p95/p99にだけ現れる遅さには、いくつかの典型パターンがあります。
特定条件下でだけ発生するN+1クエリ
通常のN+1クエリは全リクエストが一律に遅くなりますが、テールレイテンシで多いのは「関連レコード数が多いユーザーだけ」N+1が致命傷になるケースです。例えば1ユーザーあたりの子レコードが平均10件のところ、上位顧客だけ数千件持っている場合、その顧客のリクエストだけ極端に遅くなります。平均的なテストデータでは再現せず、本番の「一番データが多いアカウント」で初めて顕在化します。
コールドキャッシュ・キャッシュミス
キャッシュがヒットしている間は速いが、キャッシュの有効期限切れ直後やデプロイ直後、あるいはアクセス頻度の低いデータ(ロングテールの商品ページなど)では毎回キャッシュミスして重い処理が走ります。全体のヒット率が95%であれば平均は速く見えますが、残り5%がまさにp95付近の遅さとして表れます。
ロック待ち・行ロックの競合
同一レコードへの更新が集中するタイミング(在庫の同時更新、集計バッチとリクエストの重複など)で、一部のリクエストだけDBのロック待ちに入り数秒単位で遅延します。平時は問題なく、特定の時間帯やイベント時にだけp99が跳ねるのが特徴です。
大量データを返す一覧・エクスポート系エンドポイント
ページングをしていない、または「全件エクスポート」のような機能が一部のユーザーにだけ使われている場合、そのエンドポイントだけが突出して遅くなります。呼び出し頻度が低いためAPMのアラートに引っかからず放置されがちです。
外部APIのレイテンシ分布
決済・住所検索・AI APIなどの外部サービスは、平均レスポンスは安定していても、稀に数秒〜数十秒かかるリクエストが混在します。これを同期的に待っている自社APIは、外部サービスのテール分布をそのまま引き継ぎます。複数の外部APIを直列に呼んでいる箇所は、それぞれのテールが掛け合わさってさらに悪化します。
GCやオートスケールの谷間
言語処理系のガベージコレクションの一時停止、あるいはオートスケール中でインスタンス数が一時的に不足しているタイミングに当たったリクエストだけが遅くなります。アプリケーションコードに原因がなく、インフラ・実行環境側の問題であることが多いため、コードレビューだけでは見つかりません。
計測の仕方
パーセンタイルは実測しないと分かりません。感覚では捉えられない指標だからです。
- APM(New Relic、Datadog、Railsなら
rack-mini-profiler等)でp50/p95/p99を常時可視化する。平均値だけのダッシュボードしかない場合は、まずここを直します。 - エンドポイント単位で分布を見る。全体のp95ではなく「どのエンドポイントのp95が悪いか」まで分解しないと、改善対象が特定できません。
- 遅いリクエストのトレースを個別に確認する。p99に該当した実際のリクエストのAPMトレースを開き、DB・外部API・アプリケーションコードのどこで時間を使っているかを見ます。統計値だけでなく生トレースを見る工程は省略できません。
- 本番相当のデータ量・データの偏りで計測する。開発環境の均一なテストデータでは、テールを生む「特定ユーザーだけデータが多い」偏りが再現しません。
- 時間帯別・曜日別に分布を見る。バッチ処理や特定イベントとの重なりでp99が悪化している場合、リクエスト単体を見ていても原因が分かりません。
計測の初期段階で「p95が悪いエンドポイント上位5件」と「それぞれの遅いリクエストのトレース3〜5件」が揃えば、原因調査に入れます。エンドポイント単位の計測とレスポンスタイム改善の基本的な進め方は遅いAPIレスポンスを改善する調査と実装手順でも解説しているので、合わせて確認してください。
改善の優先順位づけ
テールレイテンシの改善は「全部直す」のではなく、影響範囲とコストで優先順位をつけます。
- 発生頻度 × ビジネスインパクトで並べる。p99の原因が「一番データ量が多い優良顧客」なら、頻度が低くても優先度は最上位になります。逆に「めったに使われない管理画面の一括エクスポート」なら後回しで構いません。
- 原因が1つのボトルネックに集約できるものから着手する。特定条件下のN+1やインデックス不足は、修正箇所が局所的で投資対効果が高いことが多いです。
- インフラ・実行環境側の問題(GC・オートスケール)は最後に回す。コード側の明らかな原因を潰してから、それでも残るテールがあれば実行環境のチューニングを検討します。
- 「平均は変えず、p95/p99だけ改善する」施策と「全体を底上げする」施策を混同しない。前者はテール原因の局所的な修正、後者はキャッシュ戦略やインフラ増強など性質が異なります。目的に合わせて手段を選びます。
外注してテールレイテンシの改善を依頼する場合は、「p95を◯◯ms以内にする」のようにパーセンタイルでゴールを合意することが重要です。平均値だけを成果指標にすると、テールが残ったまま「平均は改善した」という報告で終わってしまうことがあります。改善前後で同じデータ量・同じ時間帯の分布を比較し、Before/Afterをパーセンタイルで示してもらう進め方を推奨します。
まとめ
- 平均レスポンスタイムが正常でも、一部のユーザーだけ極端に遅いテールレイテンシは平均には現れない。p95/p99での計測と可視化がまず必要
- テールレイテンシの典型原因は、特定条件下のN+1・コールドキャッシュ・ロック待ち・大量データ返却・外部APIのレイテンシ分布・GCやオートスケールの谷間で、それぞれ調査の切り口が異なる
- 改善は全部を一律に直すのではなく、発生頻度とビジネスインパクトで優先順位をつけ、パーセンタイルでゴールを合意して進めるのが外注時も含めて成果がぶれない方法
torcheeesでは、既存プロダクトのパフォーマンス診断から、p95/p99の原因特定を踏まえた改善支援まで対応しています。「平均は速いのに一部だけ遅い」という状態でも、まずは現状のレイテンシ分布を無料相談でお聞かせください。お問い合わせはこちら。改善支援の詳細はプロダクト改善・モダナイゼーション支援、インフラ・実行環境の観点はインフラのページもご覧ください。
既存プロダクト改善に着手する前に確認すべき全体的な観点は、既存プロダクトの改善、外部チームが最初に見る観点で整理しています。