【AWS】CloudFrontのキャッシュ設定完全ガイド|TTL・invalidation・キャッシュポリシーの使い分け

2026-04-27

はじめに

CloudFrontは高速なコンテンツ配信が魅力ですが、キャッシュの設定を誤るとコンテンツが更新されない、あるいはキャッシュが効かずオリジンへのリクエストが増えるという問題が起きます。

私自身、このブログをS3 + CloudFront構成で運用しており、記事を更新してもブラウザに古いページが表示される問題や、Invalidationのコストを気にしながら設定を調整した経験があります。

この記事では、CloudFrontのキャッシュの仕組みからTTL設定、キャッシュポリシー、Invalidationの使い方まで、実務で役立つ知識を整理します。

CloudFrontのキャッシュの仕組み

CloudFrontはエッジロケーションにコンテンツをキャッシュし、ユーザーへ近いロケーションから配信します。

リクエストが来たとき、CloudFrontは次の順序で処理します。

  1. エッジキャッシュにコンテンツが存在するか確認(キャッシュヒット
  2. キャッシュがなければオリジン(S3やEC2など)へ取得しに行く(キャッシュミス
  3. オリジンから取得したコンテンツをエッジにキャッシュして返す

キャッシュヒット率(Cache Hit Ratio)が高いほどオリジンへの負荷が下がり、レスポンスも速くなります。

キャッシュキーとは

CloudFrontはデフォルトでURLのパス部分をキャッシュキーとして使います。同じURLへのリクエストはキャッシュから返されます。

クエリ文字列・ヘッダー・Cookieをキャッシュキーに含めることもできますが、含めるほどキャッシュヒット率が下がるため注意が必要です。

TTL設定の種類

TTL(Time To Live)はキャッシュの有効期間です。CloudFrontでは3種類のTTLを設定できます。

設定意味デフォルト値
Minimum TTLキャッシュの最短保持時間0秒
Maximum TTLキャッシュの最長保持時間31536000秒(1年)
Default TTLオリジンがCache-Controlを返さない場合のTTL86400秒(1日)

オリジンのCache-Controlヘッダーとの関係

オリジン(S3など)が Cache-Control: max-age=3600 を返している場合、CloudFrontはその値を尊重しますが、TTLの範囲内に丸められます

オリジンのmax-age=3600(1時間)
→ Minimum TTL=0, Maximum TTL=86400 の場合
→ CloudFrontは3600秒キャッシュする(オリジンの指定を尊重)

オリジンのmax-age=0(キャッシュなし)
→ Minimum TTL=0 の場合
→ CloudFrontはキャッシュしない

オリジンがCache-Controlを返さない場合
→ Default TTL(86400秒)が使われる

S3静的サイトでの推奨設定

S3で静的サイトをホストしている場合、ファイルの種類によってTTLを使い分けるのがベストプラクティスです。

ファイル種別Cache-Control設定理由
HTMLmax-age=0, must-revalidate記事更新がすぐ反映されるように
CSS / JS(ハッシュ付き)max-age=31536000, immutableファイル名が変わるので長期キャッシュOK
画像max-age=2592000(30日)頻繁に変わらないが長すぎも避ける
sitemap.xmlmax-age=3600(1時間)クロール頻度に合わせて短めに

S3にオブジェクトをアップロードする際、メタデータで Cache-Control を指定できます。AWS CLIでは次のように設定できます。

aws s3 cp index.html s3://your-bucket/ \\
  --cache-control "max-age=0, must-revalidate" \\
  --content-type "text/html"

キャッシュポリシーの設定方法

CloudFrontのビヘイビア(Behavior)にはキャッシュポリシーを関連付けます。マネージドポリシーを使うか、カスタムポリシーを作成する方法があります。

AWSマネージドポリシー

よく使うマネージドポリシーは以下の通りです。

ポリシー名TTL用途
CachingOptimizedDefault 86400秒S3静的サイト(デフォルト推奨)
CachingDisabled0秒キャッシュを無効にしたいAPI等
CachingOptimizedForUncompressedObjectsDefault 86400秒圧縮非対応のオリジン向け

S3の静的サイトには CachingOptimized がデフォルトで最適です。

カスタムキャッシュポリシーの作成

AWSコンソール → CloudFront → ポリシー → キャッシュポリシー → ポリシーを作成 から設定できます。

設定項目:

  • 名前: 識別しやすい名前(例:static-site-html
  • デフォルトTTL / 最小TTL / 最大TTL: 前述の値を設定
  • キャッシュキーの設定: クエリ文字列・ヘッダー・Cookieの含め方

静的サイトでHTMLだけキャッシュを短くしたい場合は、HTMLパス用のビヘイビアを別途作成してカスタムポリシーを当てるのが効果的です。

Invalidationの使い方とコスト

Invalidation(キャッシュ無効化)はエッジキャッシュを強制的に削除する機能です。コンテンツを更新したのにユーザーに反映されないときに使います。

Invalidationのコスト

最初の1,000パスは毎月無料です。それを超えると1パスあたり$0.005かかります。

/articles/laravel/artisan-key-generate/   → 1パス
/articles/laravel/*                        → 1パス(ワイルドカード)
/*                                         → 1パス(全体)

ワイルドカード /* は1パスとしてカウントされるため、全体を一括無効化する場合もコストは最小です。

AWSコンソールからの実行

  1. CloudFront → ディストリビューションを選択
  2. 「Invalidations」タブ → 「Create invalidation」
  3. パスを入力(例:/* または /articles/laravel/artisan-key-generate/

AWS CLIからの実行

# 特定パスを無効化
aws cloudfront create-invalidation \\
  --distribution-id YOUR_DISTRIBUTION_ID \\
  --paths "/articles/laravel/artisan-key-generate/*"

# 全体を無効化
aws cloudfront create-invalidation \\
  --distribution-id YOUR_DISTRIBUTION_ID \\
  --paths "/*"

Invalidationが完了するまでの時間

通常1〜5分程度で完了しますが、エッジロケーションの数によっては数分かかることもあります。AWSコンソールの「Invalidations」タブでステータスを確認できます。

S3静的サイトでの実践的な設定例

私がこのブログで採用している構成をベースにした設定例を紹介します。

構成

ユーザー → CloudFront → S3(静的ホスティング)

ビヘイビアの分け方

パスパターンキャッシュポリシーTTL設定
*.html または /カスタム(短期)Default 0秒
*.css, *.jsCachingOptimizedDefault 86400秒
*.jpg, *.png, *.webpCachingOptimizedDefault 86400秒
/sitemap*.xmlカスタム(中期)Default 3600秒

HTMLをキャッシュしない(TTL=0)設定にしておくと、記事を更新してSimply Staticでエクスポート → S3にアップロードすれば即時反映されます。InvalidationはHTMLをキャッシュする構成にしている場合のみ必要になります。

CloudFront Functionsでのindex.html補完

S3をオリジンとして使う場合、/articles/laravel/artisan-key-generate/ のようなディレクトリ形式のURLにアクセスすると AccessDenied が返ります。

これはCloudFront Functionsで解決できます。

function handler(event) {
  var request = event.request;
  var uri = request.uri;

  // 末尾がスラッシュで終わる場合はindex.htmlを補完
  if (uri.endsWith('/')) {
    request.uri += 'index.html';
  }
  // 拡張子がない場合もindex.htmlを補完
  else if (!uri.includes('.')) {
    request.uri += '/index.html';
  }

  return request;
}

このFunctionsを「ビューワーリクエスト」イベントに関連付けることで、すべてのディレクトリURLが正常に解決されます。

まとめ

CloudFrontのキャッシュ設定は、コンテンツの種類と更新頻度に合わせて使い分けることが重要です。

項目ポイント
TTLHTMLは短く(0)、CSS/JSは長く(1年)が基本
キャッシュポリシーS3静的サイトはCachingOptimizedが最適
キャッシュキークエリ文字列・ヘッダーを増やすとヒット率が下がる
Invalidation月1,000パスまで無料。/* で全体無効化が手軽
Cache-Controlオリジン側で設定するとCloudFrontが尊重する

静的サイトであればHTMLのTTLを0にしてInvalidation不要な構成にするのが、運用コストが最も低くおすすめです。

AWSAWS

Posted by 千原 耕司