HTTPキャッシュの鮮度とstale-while-revalidateの適用範囲

RFC 9111はHTTPキャッシュの保存、再利用、検証規則を定義します。max-ageは応答の鮮度期間を決め、共有キャッシュではs-maxageを利用できます。ETagやLast-Modifiedは期限切れの応答の条件付き再検証に使われます。stale-while-revalidateはRFC 9111ではなくRFC 5861の拡張機能です。指定期間中にキャッシュが期限切れの応答を返しながらバックグラウンドでの再検証を試みることを許しますが、すべてのキャッシュが対応し同じ挙動をする保証ではありません。

Fastlyのキャッシュ運用から見る適用条件

Fastlyの文書によると、応答がキャッシュに保存され、リクエストが該当するキャッシュ経路を通る場合、同社のキャッシュは期限切れの応答を返しながら非同期で再検証できます。応答がすでにキャッシュから削除されていたり、リクエストがバックエンドへ転送されたりすると、同じ動作にはなりません。これはFastlyの製品説明であり、すべてのCDNエッジで同じ更新動作や全域での同時更新が保証されるわけではありません。アクセスが少なければ、許容期間内に再検証リクエストが発生しないこともあります。

期限切れ許容期間は許容できるデータの古さを決める

Cache-Control: max-age=300, stale-while-revalidate=60は300秒有効期間内として扱い、その後最大60秒の期限切れ応答の配信を許す例です。この期間は許容するデータ鮮度に関する製品判断です。残高、権限、在庫など最新性が必要な応答に一律適用しないでください。RFC 5861は期限切れの応答中に応答を待たせない再検証を試みるよう推奨しますが、期限切れ応答の配信自体はMAYです。期間終了後は別の根拠がない限り継続すべきではありません。stale-if-errorはerror時に期限切れを返す別拡張機能で、バックグラウンドでの再検証とは異なります。

Ageから期限切れ許容期間を読む仮想タイムライン

Cache-Control: max-age=300, stale-while-revalidate=60の応答がキャッシュに残り、この拡張機能をキャッシュがサポートし、must-revalidateやs-maxageなど結果を変える別指示子・独自方針がないと仮定します。Ageは応答の現在の経過時間を示します。表は指示子が許す動作であり、すべてのCDNの実際の配信を保証しません(RFC 9111 §4.2、RFC 5861 §3)。

リクエストのAge経過時間の判定この指示子での判断
250秒max-age=300以内の有効期間内保存応答を再検証せず再利用できます。
320秒期限切れになって20秒、SWR 60秒以内キャッシュは期限切れを配信できます。配信する場合、ブロッキングせず再検証を試みるべきです。
370秒期限切れになって70秒、SWR 60秒超過SWRだけでは期限切れ応答の配信を続けられません。他の許可根拠がなければ次のリクエストは再検証を待つか、オリジンから新しい応答を得る必要があります。

stale-while-revalidate=60は応答をさらに60秒有効期間内にする指定ではありません。Ageが320秒の時点で古い応答が実際に配信されたかを確認するには、観測地点のAge、オリジンでの再検証時刻、CDNのキャッシュログを照合します。RFC 9111ではWarningヘッダーは廃止扱いとなっており、検証に必須の根拠や指標ではありません。拡張機能の対応状況、ほかのCache-Control指示子、事業者固有方針も別途確認してください。

共有キャッシュの安全性と確認

共有キャッシュのキーがURL、メソッド、Varyなどで利用者ごとの応答を分離するか確認します。private、no-store、Authorizationヘッダーを含むリクエストへの応答に関するRFC規則と例外を調べ、CDN固有ルールが意図した方針を上書きしないか検証します。Cookieや個人トークンを含む応答は明示的に分離するかキャッシュを迂回させます。ブラウザー・エッジ対応、Age、条件付きリクエスト、シールドやパージの設定、再検証の発生頻度を実応答とログで試験してください。SWRは遅延を隠せますが、オリジン負荷の低減や常に最新の内容を保証しません。

参考資料