Skip to content

非公式本サイトは非公式の日本語ドキュメントであり、Cloudflare 公式サイトではありません。最新情報はdevelopers.cloudflare.comをご確認ください。

デバッグ

最終更新 Markdown で表示Agent セットアップ

キャッシュの挙動が期待と違うときは、まずレスポンスヘッダー Cf-Cache-Status を確認します。すべてのレスポンスに付き、その値でそのリクエストに何が起きたかが分かります。

Cf-Cache-Status を確認する

同じ URL に 2 回リクエストを送り、ヘッダーを比較します。

curl -I https://my-worker.example.workers.dev/api/users/42
curl -I https://my-worker.example.workers.dev/api/users/42

ステータス値を、次のシナリオと照合します。

すべてのリクエストで Worker が実行される

Cf-Cache-Status がありません。Wrangler のバージョンが 4.69.0 以上であることと、wrangler.toml または wrangler.jsonc でその Worker に cache.enabled = true があることを確認します。

Cf-Cache-Status が毎回 MISS、または DYNAMIC、または BYPASS です。キャッシュに何も保存されていないか、バイパスルールが発動しています。

Cache-Control ヘッダーを確認します。 レスポンスには、キャッシュ可能にするディレクティブが必要です。

  • public, max-age=N — Cloudflare とブラウザーに N 秒間キャッシュされます。

Cache-Control: private または no-store のレスポンスは保存されず、Cf-Cache-StatusBYPASS です。

Cache-Control: no-cache のレスポンスは 保存されます が、Cloudflare は以降のすべてのリクエストを stale とみなし、配信前にご自身の Worker に問い合わせます。正確な Cf-Cache-Status は、stale-while-revalidate も設定されているかによって変わります。

  • Cache-Control: no-cache だけの場合、以降のすべてのリクエストでインライン再検証が走ります。Worker が 304 Not Modified を返すと Cf-Cache-StatusREVALIDATED(本文はキャッシュから配信)、新しい 200 を返すと EXPIRED(本文は置き換え)です。
  • Cache-Control: no-cache, stale-while-revalidate=N の場合、キャッシュされた本文はすぐ配信され、Worker はバックグラウンドで実行されます。SWR ウィンドウ中の Cf-Cache-StatusUPDATING です。

長期間ヒットさせたい場合は、代わりに max-age を使います。no-cache はバイパスではありません を参照してください。

レスポンスに Cache-Control ヘッダーが ない 場合、挙動はステータスコードに依存します。Workers Caching は RFC 9111 のヒューリスティック鮮度 を適用し、デフォルトでキャッシュ可能なステータスコードをヒューリスティック TTL でキャッシュします。たとえば 200 は 2 時間、404 は 3 分です。デフォルト TTL の一覧は、設定リファレンスの Cache-Control ヘッダーがないレスポンスもキャッシュされる を参照してください。これらのデフォルトを使いたくない場合は、レスポンスに Cache-Control を明示します。

リクエストメソッドを確認します。 キャッシュされるのは GETHEAD だけです。それ以外は BYPASS です。同じ URL の GETHEAD は同じキャッシュエントリを共有します。どちらのメソッドからキャッシュを埋めるかは キャッシュキー を参照してください。

自動バイパス条件を確認します。 Cloudflare は次の場合にキャッシュをバイパスします。

  • レスポンスに Set-Cookie ヘッダーがある。
  • リクエストに Authorization ヘッダーがある。ただしレスポンスが明示的に Cache-Control: publicmust-revalidate、または s-maxage を設定している場合を除く。

Worker が無条件に Set-Cookie を付ける(例: すべてのレスポンスにセッション Cookie)と、レスポンスはキャッシュされません。キャッシュ可能なレスポンスから Cookie を外すか、Cookie 設定とキャッシュ可能なレスポンスを別ルートに分けます。

ステータスコードを確認します。 Workers Caching は RFC 9111 に従います。デフォルトでキャッシュできないステータスコード(例: 401403500)のレスポンスは、キャッシュ可能なディレクティブを明示しない限り保存されません。

一部のステータスコードは、明示的な Cache-Control があってもキャッシュされません。

  • 520526 は Cloudflare のフェイルセーフレスポンスとして扱われ、保存されません。
  • Worker が返す 206 Partial Content は保存されません。Workers Caching は Range リクエストを、Worker から全文を取得してキャッシュエントリから切り出すことで自ら処理します。Worker が独自の 206 を返すとそのレスポンスはキャッシュ不可になります。代わりに全文の 200 を返してください。Range リクエスト を参照してください。

最初のリクエストのあとも Worker が実行される

Cf-Cache-Status は最初のリクエストで MISS で、以降も MISS です。

キャッシュが分割されている可能性が高いです。 キャッシュキーにはリクエストパス、対象エントリポイント、呼び出しの ctx.props が含まれます。見た目が同じ 2 つのリクエストでも、これらが違うとキャッシュキーが異なります。

よくある原因:

  • リクエスト間で URL パスやクエリ文字列が違う(末尾のスラッシュも区別されます)。
  • 呼び出し元の Worker がリクエストごとに異なる ctx.props を渡している(例: 異なるユーザー ID)。
  • 同じ Worker の異なる 名前付きエントリポイント にリクエストが届いている。

Cloudflare は現在、キャッシュキーの構成を公開していないため、計算されたキーを直接見ることはできません。代わりに キャッシュキー に列挙された要素を順に確認し、両方のリクエストで同じであることを検証します。

デプロイ後にキャッシュヒット率が下がった

デフォルト設定では想定どおりです。デフォルトでは Worker のバージョンがキャッシュキーの一部 なので、新しいバージョンはコールドキャッシュから始まり、前バージョンのキャッシュ済みレスポンスを再利用できません。デプロイ直後の最初のリクエストはミスになり、新しいバージョンのキャッシュが埋まるにつれてヒット率は回復します。

頻繁にデプロイし、デプロイ間でレスポンスがほとんど変わらない場合は、cache.cross_version_cache を有効にすると、バージョン間でキャッシュ済みレスポンスを共有し、デプロイのたびにキャッシュがリセットされるのを避けられます。トレードオフとして、キャッシュに影響する変更はすぐには適用されません。次のセクションを参照してください。

デプロイ後も古いコンテンツがキャッシュから配信される

デフォルトでは、Worker のバージョンがキャッシュキーの一部で新しいバージョンはコールドキャッシュから始まるため、デプロイはすぐに効きます。前バージョンのレスポンスが見える場合は、バージョン間でキャッシュエントリを共有する cache.cross_version_cache が有効です。cross_version_cache を維持したままデプロイをすぐ反映するには:

コンテンツを変えてもキャッシュが更新されない

オリジンのデータは変わったのに、リクエストがまだ古いコンテンツを返す場合:

  • TTL を確認します。 レスポンスは max-age 秒間キャッシュされます。まだ鮮度ウィンドウ内のレスポンスを見ている可能性があります。
  • 対象レスポンスをパージします。 タグまたはパスプレフィックス付きで ctx.cache.purge() を使い、特定エントリを無効化します。キャッシュのパージ を参照してください。
  • 書き込み時にタグを付けます。 Cache-Tag ヘッダーを設定していないと、タグではパージできません。キャッシュするレスポンスにタグを付けてデプロイし、新しいエントリが書かれたあとでパージできるようになります。

2 つの呼び出し元が互いのキャッシュ済みレスポンスを受け取る

呼び出し元ごとの認可コンテキストに ctx.props を使っていれば、これは起きません。起きている場合は、次のいずれかです。

  • キャッシュキーに含まれないヘッダーやクエリパラメータで呼び出し元を認証している。認可入力を ctx.props に移します。ctx.props によるマルチテナント安全性 を参照してください。
  • サービスバインディングの呼び出しで、ユーザー固有のクエリパラメータが欠けている。クエリ文字列はキャッシュキーの一部です。呼び出し元ごとのリクエストパスが実際に違うことを確認します。

Cf-Cache-Status: UPDATING が常に出る

UPDATING は、stale なキャッシュからレスポンスを配信しつつ、バックグラウンドで Worker が更新していることを意味します。stale-while-revalidate を使っているときの想定どおりの挙動です。

想定より多く UPDATING が出る場合:

  • max-age がリクエストの到着間隔より短い。max-age 経過後に届くリクエストは、すべて再検証を起こします。
  • max-age=0, stale-while-revalidate=<large> では、すべての リクエストが再検証を起こします。これは「常にキャッシュから配信する」挙動であり、「Worker を実行しない」ではありません。TTL と stale-while-revalidate の値を選ぶ を参照してください。

Cf-Cache-Status: UPDATING が一度も出ない

UPDATING が出るのは、次の すべて が真のときだけです。

  • キャッシュエントリがあり、鮮度ウィンドウを過ぎている(stale)。
  • レスポンスに stale-while-revalidate=N があり、エントリが stale になってから N 秒以内にリクエストが届く。
  • レスポンスに s-maxagemust-revalidateproxy-revalidateない

いずれかが偽だと、stale エントリへのリクエストはインライン再検証に落ち、EXPIRED(Worker が新しい本文を返した)または REVALIDATED(Worker が 304 Not Modified を返した)になります。

UPDATING が出ないよくある理由:

  • レスポンスに stale-while-revalidate ディレクティブがない。 デフォルトの SWR ウィンドウは 0 なので、明示しないと stale リクエストはすべてフォアグラウンド再検証になります。
  • s-maxagemust-revalidate、または proxy-revalidate がある。 RFC 9111 §4.2.4 では、これらのディレクティブは stale コンテンツの配信を禁じるため、いずれかがあると Cloudflare は stale-while-revalidate(と stale-if-error)を無効にします。stale 配信を使いたい場合は、エッジの鮮度ウィンドウに max-age を使います。
  • SWR ウィンドウが過ぎている。 max-age=60, stale-while-revalidate=120 なら、エントリが stale になってから 120 秒以内のリクエストで UPDATING が出ます。それ以降はインライン再検証に戻ります。

Cf-Cache-Status: STALE が想定外に出る

STALE は、キャッシュを更新するはずだったリクエストで Worker がエラーになったため、以前キャッシュしたレスポンスを Cloudflare が配信したことを意味します。たとえば Worker が例外を投げた、タイムアウトした、5xx を返した、などです。これは stale-if-error の挙動です。stale-if-error でエラー時に stale を配信する を参照してください。

STALE が出て想定外の場合:

  • キャッシュの充填または再検証で Worker が失敗しています。 新しいレスポンスを出すべきリクエストのエラーを Workers observability ダッシュボード で確認します。クライアントが 5xx ではなく stale レスポンスを見ているため、実際の障害が隠されています。
  • stale-if-error を明示しておらず、レスポンスに s-maxage / must-revalidate / proxy-revalidate もない。 この場合、Cloudflare のデフォルトは、キャッシュエントリがパージされていない限り、Worker エラー時に期限なく stale レスポンスを配信することです。エラーをすぐクライアントに見せたい場合は、Cache-Controlstale-if-error=0 を設定します。詳細は stale-if-error でエラー時に stale を配信する を参照してください。
  • 以前デプロイしたバージョンが配信されています。 修正をデプロイしても STALE が出続ける場合、壊れたバージョンのキャッシュエントリがエラーのたびに配信されています。対象エントリを パージ し、現在のバージョンから新たに充填します。

クライアント側の可観測性で通常の HITSTALE を区別するには、レスポンスと一緒に Cf-Cache-Status を記録します。Worker が失敗していてクライアントには見えていないことを示すシグナルは STALE だけです。

レスポンスがサイズ上限を超えている

レスポンスが大きすぎてキャッシュできない場合、Cloudflare は保存しません。ほかはキャッシュ可能に見えても、毎回 Cf-Cache-Status: MISS になります。

プランごとのレスポンスサイズ上限は キャッシュ可能なサイズ上限 を参照してください。ローンチ時点では、Workers Caching のすべてのレスポンスに Free プランのサイズ上限が適用されます。詳細は レスポンスサイズ を参照してください。

さらに可視性が必要

ローンチ時点の主なデバッグ面は、Cf-Cache-Status レスポンスヘッダーと、Workers observability ダッシュボード の呼び出しごとのキャッシュヒット情報です。

役に立ちましたか?