diagnosing-endpoint-performance について
特定の遅い、高コスト、または不安定なエンドポイントを調べる診断スキルです。キャッシュ、マテリアライズ可否、クエリ履歴、呼び出しコストを確認して具体策を示し、クエリ変更前にユーザーの承認を求めます。
主な機能
- 01エンドポイント設定とバージョンの確認
- 02キャッシュ TTL とマテリアライズの評価
- 03マテリアライズ不可の理由を確認
- 04呼び出し頻度とコストの確認
- 05キャッシュ、マテリアライズ、書き換え、ロールバックの提案
活用シーン
- 01タイムアウトするエンドポイントの診断
- 02高コストなエンドポイントの呼び出し分析
- 03クエリをマテリアライズできるか判断
- 04最近のエンドポイント版の回帰を確認
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ posthog/ skills --skill diagnosing-endpoint-performanceインストール後、Claude Code で/diagnosing-endpoint-performanceを入力して読み込まれたか確認します。
詳細
エンドポイントのパフォーマンスを診断する
このスキルでは、処理が遅い、コストが高い、または信頼性に欠ける特定のエンドポイントを調査し、
具体的な推奨事項を提示します。候補を見つける auditing-endpoints の詳細な調査を行うスキルです。
このスキルを使う場面
- 「このエンドポイントは遅い/タイムアウトする」
- 「エンドポイントがコスト上限に達しているのはなぜですか?」
- 「X をマテリアライズすべきですか?」
auditing-endpointsで、マテリアライズに失敗している、または呼び出しコストが高いと判明したエンドポイント- ユーザーが特定のエンドポイントについて相談したい場合
プロジェクト全体についての質問(「何を整理すべきですか?」)の場合は、まず auditing-endpoints を使ってください。
利用可能なツール
| ツール | 目的 |
|---|---|
endpoint-get | エンドポイントの全設定:クエリ、現在のバージョン、data_freshness_seconds、マテリアライズの状態 |
endpoint-versions | すべてのバージョンの履歴(クエリ+マテリアライズの状態)。現在のバージョンも確認できます |
endpoint-materialization-status | マテリアライズの適格性、現在の状態、最終実行、最後に発生したエラー |
endpoints-materialization-preview | マテリアライズされたクエリの内容と、適格でない場合はその理由 |
endpoints-last-execution-times | 最後に呼び出された日時(エンドポイントが現在も使われているかを確認する健全性チェック) |
execute-sql | query_log を照会して、エンドポイント単位の呼び出し頻度と各呼び出しの所要時間/バイト数を確認 |
判断の流れ
推奨事項を決めるときは、次の順に確認してください。最初に当てはまる項目が、最も低コストな解決策です。
ステップ 1 — そもそもキャッシュされていますか?
エンドポイントを取得し、data_freshness_seconds を確認してください(この値はキャッシュ TTL と、マテリアライズされている場合は更新間隔の両方を設定します)。ユーザーのトラフィックが同じパラメーターで
この期間内に繰り返し呼び出す場合、最初の呼び出し以降はすべてキャッシュヒットとなり、実質的にコストはかかりません。
- TTL がデフォルト(24 時間/86400 秒)で、データをそれより新しくする必要がない場合 → これで完了です。変更は不要です。
- TTL が最小値の 900 秒(15 分)で、ユーザーが 1 分あたり何度もエンドポイントを呼び出している場合 →
TTL を増やしてください。ほとんどの場合、これが最も低コストで最初に試すべき方法です。(
data_freshness_secondsは列挙値で、900、1800、3600、21600、43200、86400、604800 です。15 分未満の値はありません。) - データを最新に保つ必要があるため TTL が最小値になっている場合(例:リアルタイムダッシュボード)→ キャッシュは役に立たないため、ステップ 2 に進んでください。
ここでは変数の形も重要です。呼び出しのたびに異なる user_id や date_from
の値が渡される場合、キャッシュには異なるキーが多数作られるため、TTL を増やしても効果は小さくなります。ほとんどの呼び出しで同じ少数のパラメーターの組み合わせが使われる場合は、キャッシュが大きな効果を発揮します。
ステップ 2 — マテリアライズすべきですか?
マテリアライズでは、クエリを事前計算して保存済みビューにし、スケジュールに従って更新します。読み取りはほぼ瞬時になりますが、その代わりに更新間隔と同等のデータの古さが生じ、マテリアライズ自体にストレージとコンピューティングリソースが必要になります。
endpoints-materialization-preview を呼び出します。レスポンスには次の情報が含まれます。
- 対象で、変換も問題なし → 有力な候補です。特に、フィルターの形(変数、内訳)が予測可能なエンドポイントでは、有効化を推奨します。
- 対象外で、却下理由がある → マテリアライズできません。理由が次のステップ(ステップ 3 — 書き換え)のヒントになることもよくあります。
- 対象だが、変換が複雑(範囲ペアが多い、集計の再導出が複雑) → マテリアライズは機能しますが、効果はあまり期待できないかもしれません。有効化する前にその点を伝えるとよいでしょう。
マテリアライズを有効にした場合、呼び出し元はすべてのマテリアライズ対象変数を渡す必要があります。変数を渡さない呼び出しは拒否されます(セキュリティ上の理由:フィルターのないデータが返されるのを防ぐためです)。推奨とあわせて、どの変数が必須になるかも伝えてください。
ステップ 3 — クエリを書き換える必要がありますか?
対象外の SQL エンドポイントでは、endpoints-materialization-preview の却下理由が判断の手がかりになります。このツールは必ず解決します。理由を確認し、以下の項目と照らし合わせてください。これらはよくあるケースをまとめたもので、サーバーが行うすべてのチェックを網羅しているわけではありません。そのため、食い違う場合は実際の理由を優先してください。書き換え案は手動で提案します。
- コホート内訳/比較モードによる却下 → 通常のプロパティ内訳は問題なくマテリアライズできますが、コホート内訳のみがブロックされます。コホート内訳をプロパティ内訳に置き換えてください。比較モードは Trends エンドポイントではマテリアライズできますが、それ以外のクエリ種別では比較モードを外し、比較期間を変数として公開してください。
- 変数と組み合わされた
JOIN→ トップレベルのJOINに変数フィルターを組み合わせると、マテリアライズは拒否されます。変数を適用すると結合後の行数が変わり、誤った結果が気づかれないまま生成されるためです(例:LEFT JOINの不一致行では変数列が失われます)。変数が単一のテーブルをフィルターするように構造を変えてください。結合後にフィルターを適用するのではなく、結合するサブクエリ/CTE にフィルターを押し込んでください。これは「問題なさそうに見えるのにマテリアライズできない」ケースで最もよくある落とし穴です。 - 「変数が不足」/スキャン範囲が広すぎる → クエリはフィルターなしで大量のデータを読み取っています。必須の期間変数(例:
date_from、lookback_days)を追加するよう促してください。 *を使用した HogQL/非決定的関数 → 選択する列を絞り、可能であればnow()/today()を変数に置き換えてください。- 該当する項目がない → 上記の一覧は網羅的ではありません。実際のチェックでは、ここに記載されていない形式(
OR内の変数、別の変数との比較に使われる変数、HAVING句内の変数、サポートされていない演算子、マテリアライズできないクエリ種別)も拒否されます。却下理由をそのままユーザーに示し、最も近い項目に無理に当てはめず、その理由から直接判断してください。書き換えに相当する方法がない理由もあります。たとえば、OR {variables.x} = 'all'のように変数を任意指定する慣用表現が該当します。その場合はクエリの動作を変えるのではなく、書き換え方法がないことを伝えてください。
endpoint-versions を確認し、クエリが最近変更されたかどうかを調べてください。問題の再発は特定のコミットが原因であることが多く、その場合はクエリを書き換えるより、該当バージョンに戻すほうが速いことがあります。
ステップ 4 — 遅いバージョンが実際に呼び出されているか確認する
デフォルトで実行されるのは最新バージョンのみです。古いバージョンが実行されるのは、呼び出し元が ?version=N を指定した場合だけです。
そのため、調整すべきバージョンはほとんどの場合、現在のバージョンです。ただし、指定された古いバージョンが原因の場合は例外です。endpoint-versions を呼び出し、各バージョンの last_executed_at を確認して、最近実行されたバージョンを特定してください。last_executed_at が null、または長期間更新されていないマテリアライズ済みバージョンは、調整するよりマテリアライズを解除するか削除する候補です(まず確認してください。この指標に含まれるのは API キーによる実行のみであり、データが少ない場合があります)。
エンドポイントレベルの呼び出し頻度と呼び出しごとのコストを確認するには、execute-sql で query_log をクエリしてください。query_duration_ms、read_rows、read_bytes が含まれているため、エンドポイントの呼び出しが実際にどれほど重いかを確認するのに便利です。
SELECT count() AS calls, max(query_start_time) AS last_called, avg(query_duration_ms) AS avg_ms
FROM query_log
WHERE name = '<endpoint_name>' AND endpoint LIKE '%/endpoints/%' AND is_personal_api_key_request
ワークフロー
- 名前でエンドポイントを特定します。ユーザーから URL が提供された場合は、
/api/projects/{team_id}/endpoints/{name}/runから名前を解析します。 endpoint-getで完全な設定を取得します。data_freshness_seconds、is_materialized、現在のバージョン、クエリの種類を確認します。endpoint-materialization-statusでマテリアライズの状態を確認します(失敗しているか、対象となるか)。endpoint-versionsでクエリの履歴と現在のバージョンを確認します(?version=Nが指定されない限り、呼び出し元が実行するバージョンです)。- ユーザーが具体的な症状(「タイムアウトする」「メモリ制限」「非常に遅い」)を伝えた場合は、上記の判断フローに沿って進めます。それ以外の場合は、4 つの確認項目を提示し、どれに該当するか尋ねます。
- TTL の延長、マテリアライズ、書き換え、ロールバックのいずれかを具体的に提案し、適用前に確認します。
やり取りの例
User: "monthly_active_users is timing out for some callers"
Agent steps:
- endpoint-get monthly_active_users → HogQL endpoint, data_freshness_seconds=900,
is_materialized=false, current version v4
- endpoint-materialization-status monthly_active_users → not materialised; eligible: true
- endpoint-versions monthly_active_users
→ v4 is current; v1–v3 are prior query revisions (callers hit v4 unless pinned)
- endpoints-materialization-preview → eligible, clean transform with one range pair
- "Three things stand out:
1. Cache TTL is 900 seconds (the 15-min floor), but the data is
aggregating a month — that aggressive a refresh probably isn't
necessary. Bumping to 1 hour (3600s) would dramatically reduce
ClickHouse load.
2. It's eligible for materialisation with a clean transform. If
callers can tolerate 5-15 minute staleness, materialisation
would make reads near-instant.
3. v4 is the current version, so callers hit it by default — the
tuning target is clear.
Quickest win: bump TTL to 3600s. Bigger win: materialise.
Which trade-off matches your needs? If you need real-time freshness,
neither helps and we'd need to rewrite the query — likely narrowing
the aggregation window."
重要な注意事項
- ほとんどの場合、最初に試すべきなのはキャッシュです。 無料で、すぐに元に戻せ、データの意味も変わりません。TTL を長くすれば済む場合に、すぐマテリアライズに進まないでください。
- マテリアライズには隠れたコストがあります。 マテリアライズドビューのストレージ、更新時の計算コスト、そして呼び出し元がすべての変数を渡す必要があります。
- ユーザーの許可なくクエリを書き換えないでください。 クエリを変更すると新しいバージョンが作成され、呼び出し元で問題が発生する可能性があります!!!変更案を提示し、承認を得てから適用してください。
- 使用状況を示す指標は 3 つあります。
endpoint-getのlast_executed_atはエンドポイントレベルの最近の実行状況、endpoint-versionsは各バージョン固有のlast_executed_at、execute-sql経由のquery_logはエンドポイントレベルの呼び出し頻度と呼び出しごとのコストを示します。いずれも個人用 API キーによる呼び出しのみが対象で、バージョンごとの実行頻度のデータは少ない場合があります。バージョンが使われなくなったと判断する前に、ユーザーに確認してください。 - 「適切な」修正方法はクエリではなく SLA によって決まります。 マテリアライズを提案する前に、許容できるデータの古さを必ずユーザーに尋ねてください。更新に 15 分かかるマテリアライズドビューは、どれだけ低コストでも、リアルタイムのダッシュボードには適しません。
- 不足している点を PostHog に伝えてください。 診断で製品上の制限(対象となる条件、TTL の列挙値、必須変数など)が見つかった場合は、
agent-feedbackを通じてチームに知らせてください。