CloudFrontがタグベースのキャッシュInvalidationに対応したので試してみた

CloudFrontがタグベースのキャッシュInvalidationに対応したので試してみた

CloudFrontがキャッシュタグによるInvalidationに対応しました。S3オリジン+CloudFormationで検証環境を構築し、 共通タグでの一括無効化と、特定タグでの選択的無効化の動作を確認しました。
2026.04.30

2026年4月29日、Amazon CloudFrontがキャッシュタグによるInvalidationに対応しました。

https://aws.amazon.com/about-aws/whats-new/2026/04/cloudfront-invalidation-cache-tag/

従来のCloudFront Invalidationでは、URLパスを個別に指定するか、ワイルドカード(/*)で広範囲にキャッシュを消すしかありませんでした。今回のアップデートにより、オリジンのレスポンスヘッダーでオブジェクトにタグを付与し、そのタグを指定して一括Invalidationできるようになっています。

S3オリジン+CloudFormationで検証環境を構築し、実際の動作を確認してみました。

キャッシュタグInvalidationの仕組み

公式ドキュメントの内容をもとに、仕組みを整理します。

https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/invalidation-by-tags.html

3ステップで利用開始

  1. ディストリビューションに CacheTagConfig を設定: タグを読み取るHTTPヘッダー名を指定します
  2. オリジンがレスポンスヘッダーにタグを付与: カンマ区切りで複数タグを指定できます
  3. #タグ名 でInvalidation: --paths "#version:v1" のように # プレフィックスで指定します

S3オリジンの場合、オブジェクトのメタデータにタグを設定するだけで利用できます。S3が x-amz-meta-<キー名> ヘッダーとして自動返却する仕組みです。

S3オブジェクトのメタデータ:
  cache-tag: "page:products, version:v1, category:electronics"
    ↓ S3が自動変換
レスポンスヘッダー:
  x-amz-meta-cache-tag: page:products, version:v1, category:electronics
    ↓ CloudFrontが読み取り
キャッシュタグとして保存: [page:products] [version:v1] [category:electronics]

タグの仕様

項目 制限
1オブジェクトあたりの最大タグ数 50(超過分は無視)
1タグの最大文字数 256
使用可能文字 ASCII 33〜126(スペース・カンマ・制御文字不可)
大文字小文字 区別なし

※ タグ値そのものにカンマやスペースは含められません。カンマはタグ間の区切り文字として使用され、区切り前後のスペースはパース時にトリムされます。つまり tag1,tag2tag1, tag2 は同等に扱われます。

料金

タグ1つ = パス1つ分として課金されます。従来のパスInvalidationと同じ料金体系(月1,000パスまで無料、以降1パスあたり$0.005)です。

ポイントは、タグに紐づくオブジェクトが100個でも1万個でも、タグ指定1回 = 1パス分の課金で済むことです。

https://aws.amazon.com/cloudfront/pricing/

クォータ

項目 制限
パスまたはタグの発行レート 毎秒150件(パス・タグ合算)
ワイルドカードInvalidation 毎秒1件
1タグあたりの処理対象ファイル数 上限なし

タグはパスと同じクォータを共有し、タグ1つが1パスとしてカウントされます。詳細は公式のクォータページを参照してください。

検証環境の構築(CloudFormation)

CloudFormationで検証環境を構築します。CacheTagConfig はCloudFormationでサポートされています。

https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-cloudfront-distribution-cachetagconfig.html

CloudFormation テンプレート
AWSTemplateFormatVersion: '2010-09-09'
Description: CloudFront Cache Tag Invalidation Test Stack

Resources:
  S3Bucket:
    Type: AWS::S3::Bucket
    Properties:
      BucketName: !Sub 'cf-cache-tag-test-${AWS::AccountId}'

  BucketPolicy:
    Type: AWS::S3::BucketPolicy
    Properties:
      Bucket: !Ref S3Bucket
      PolicyDocument:
        Version: '2012-10-17'
        Statement:
          - Sid: AllowCloudFrontServicePrincipal
            Effect: Allow
            Principal:
              Service: cloudfront.amazonaws.com
            Action: s3:GetObject
            Resource: !Sub '${S3Bucket.Arn}/*'
            Condition:
              StringEquals:
                AWS:SourceArn: !Sub 'arn:aws:cloudfront::${AWS::AccountId}:distribution/${Distribution}'

  OAC:
    Type: AWS::CloudFront::OriginAccessControl
    Properties:
      OriginAccessControlConfig:
        Name: !Sub 'cache-tag-test-oac-${AWS::AccountId}'
        OriginAccessControlOriginType: s3
        SigningBehavior: always
        SigningProtocol: sigv4

  Distribution:
    Type: AWS::CloudFront::Distribution
    Properties:
      DistributionConfig:
        Comment: Cache Tag Invalidation Test
        Enabled: true
        DefaultRootObject: index.html
        CacheTagConfig:
          HeaderName: x-amz-meta-cache-tag
        Origins:
          - Id: S3Origin
            DomainName: !GetAtt S3Bucket.RegionalDomainName
            OriginAccessControlId: !Ref OAC
            S3OriginConfig:
              OriginAccessIdentity: ''
        DefaultCacheBehavior:
          TargetOriginId: S3Origin
          ViewerProtocolPolicy: redirect-to-https
          Compress: true
          ForwardedValues:
            QueryString: false
          DefaultTTL: 3600
          MinTTL: 180
          MaxTTL: 3600

Outputs:
  BucketName:
    Value: !Ref S3Bucket
  DistributionId:
    Value: !Ref Distribution
  DomainName:
    Value: !GetAtt Distribution.DomainName

今回のアップデートのコア設定は CacheTagConfig です。

    Type: AWS::CloudFront::Distribution
    Properties:
      DistributionConfig:
        CacheTagConfig:
          HeaderName: x-amz-meta-cache-tag

S3メタデータのキー cache-tagx-amz-meta-cache-tag ヘッダーとして返却されるので、HeaderName にそれを指定しています。

キャッシュ設定にはマネージドキャッシュポリシー(CachingOptimized)ではなく、レガシー設定(ForwardedValues)を使用しています。検証時、CachingOptimized ではS3オリジンが Cache-Control ヘッダーを返さない場合にCloudFrontが条件付きリクエストでオリジンに問い合わせてしまい、キャッシュが安定しない挙動がありました。レガシー設定でMinTTLを180秒に設定し、S3側にも Cache-Control: max-age=300 を付与することで、オリジンのキャッシュ指示を尊重しつつ安定したキャッシュ動作を確認できています。

デプロイ

aws cloudformation deploy \
  --stack-name cf-cache-tag-test \
  --template-file template.yaml \
  --region us-east-1

テスト用コンテンツのアップロード

S3オブジェクトにメタデータ(キャッシュタグ)と Cache-Control ヘッダーを付与してアップロードします。

aws s3api put-object --bucket "$BUCKET" --key products.html \
  --body products.html --content-type text/html \
  --cache-control "max-age=300" \
  --metadata '{"cache-tag":"page:products, version:v1, category:electronics"}'

--metadatacache-tag キーに、カンマ区切りでタグを指定しています。他のファイルも同様にアップロードします。

動作検証

2つのテストケースで動作を確認します。

CloudFormationのOutputsからディストリビューションIDを取得しておきます。

DIST_ID=$(aws cloudformation describe-stacks \
  --stack-name cf-cache-tag-test \
  --query "Stacks[0].Outputs[?OutputKey=='DistributionId'].OutputValue" \
  --output text)

テスト構成

ファイル タグ
index.html page:home, version:v1
products.html page:products, version:v1, category:electronics
about.html page:about, version:v1

3ファイルすべてが version:v1 タグを共有し、page: で始まるタグはファイルごとに異なります。

TEST A: 共通タグで一括Invalidation(#version:v1

3ファイルすべてが version:v1 タグを持っています。各ファイルに複数回アクセスしてキャッシュを温めた上で、このタグを指定してInvalidationを実行します。

aws cloudfront create-invalidation \
  --distribution-id "$DIST_ID" \
  --paths "#version:v1"

パスの代わりに # プレフィックス付きのタグ名を指定するだけです。# はシェルでコメントとして解釈されるため、ダブルクォートで囲む必要があります。

結果

ファイル Invalidation前 Invalidation後
index.html Hit Miss
products.html Hit Miss
about.html Hit Miss

X-Cache: Miss from cloudfront はキャッシュが無効化され、オリジンから再取得されたことを示します。

全ファイルのキャッシュが無効化されました。Invalidationの発行から完了まで約18秒でした(公式ドキュメントではP95で25秒未満)。

TEST B: 選択的Invalidation(#page:products

次に、キャッシュを再度温めた上で、page:products タグを指定してInvalidationを実行します。このタグを持つのは products.html のみです。

aws cloudfront create-invalidation \
  --distribution-id "$DIST_ID" \
  --paths "#page:products"

結果

ファイル Invalidation前 Invalidation後
index.html Hit Hit
products.html Hit Miss
about.html Hit Hit

products.html だけがキャッシュ無効化され、index.html と about.html はキャッシュヒットを維持しています。発行から完了まで約22秒でした。

これが従来のワイルドカード(/products/*)との決定的な違いです。タグで意味的にグルーピングすることで、無関係なコンテンツのキャッシュを消さずに済みます。

従来手法との比較

従来(パス指定) キャッシュタグ
指定方法 /products/123.html/products/* #brand:acme
精度 パス構造に依存。無関係なコンテンツを巻き込みやすい 意味的なグルーピングで必要なものだけ無効化
運用負荷 対象URLの追跡・列挙が必要 アプリ側でタグを付けておけば1リクエストで完了
キャッシュヒット率 ワイルドカードで下がりやすい 関係ないキャッシュが残るので高く維持
オリジン負荷 消しすぎた分だけ再取得が発生 最小限の再取得で済む
コスト 個別URL列挙はパス数分課金。ワイルドカードは1パス分だが、オリジン転送料が増大 タグ1つ=1パス分の課金。紐づくオブジェクト数に関係なく定額。オリジン転送料も最小限

キャッシュタグにより、「何を消すか」の判断がURL構造からアプリケーションの意味(ブランド、バージョン、ユーザーなど)に移るのが本質的な変化です。

タグ設計のTips

公式ドキュメントでは以下のユースケース例が紹介されています。

ユースケース タグ例 Invalidation例
ECサイトの商品カタログ category:electronics, brand:acme, product:12345 #brand:acme でACME全商品を一括無効化
ユーザー生成コンテンツ user:12345, content-type:image #user:12345 で退会ユーザーのコンテンツを一括削除
コンテンツバージョニング version:v2, template:homepage #version:v2 でデプロイ時にv2コンテンツを一括無効化

いずれも キー:値 形式で統一されています。これに倣い、自分のプロジェクトでもプレフィックスをルール化しておくと運用時に迷いません。1オブジェクトに複数タグを付与できるので、複数の軸で横断的にInvalidationできます。

注意点

  • オプトイン必須: CacheTagConfig 未設定のディストリビューションではタグが無視されます
  • ヘッダー名の変更に注意: CacheTagConfig のヘッダー名を変更すると、旧ヘッダーでキャッシュされたオブジェクトにはタグInvalidationが効かなくなります。変更前にパスInvalidation(/*)が必要です
  • タグ変更は既存キャッシュに反映されない: S3メタデータのタグを変更しても、CloudFrontに既にキャッシュされたオブジェクトのタグは更新されません。新しいタグでInvalidationするには、先にパスInvalidationで既存キャッシュを削除し、新しいタグ付きのレスポンスを再キャッシュさせる必要があります
  • CacheTagConfig削除時: 削除しても既存キャッシュはTTL満了まで通常通り配信されます
  • 後方互換: 従来のパス・ワイルドカードInvalidationは引き続き利用可能です
  • 全バリアントが対象: タグでInvalidationすると、Cookie・ヘッダー・クエリ文字列によるキャッシュバリアントもすべて無効化されます。特定のバリアントだけを残すことはできません

まとめ

CloudFrontがキャッシュタグによるInvalidationに対応し、URL構造に依存しない柔軟なキャッシュ管理が可能になりました。

今回の検証では、S3オブジェクトのメタデータにタグを設定し、#version:v1 で3ファイル一括無効化、#page:products で1ファイルだけ選択的に無効化できることを確認しました。ワイルドカードによるキャッシュの消しすぎを避け、キャッシュヒット率を高く維持しながら、必要なコンテンツだけを精密にInvalidationできます。

CloudFormationにも対応しており、従来のパスInvalidationとの併用もできるので、段階的に導入できます。

今回はS3オリジンで検証しましたが、より効果を発揮するのは動的コンテンツを配信するCMSオリジンのケースです。

例えば、記事の更新時にCMSがレスポンスヘッダーで article:12345, category:tech, author:suzuki のようなタグを返すように設定したとします。これにより、特定カテゴリの記事一括更新や、著者の所属変更に伴うプロフィール情報の差し替えを、#category:tech や #author:suzuki の1リクエストで即座に反映できるようになります。

コンテンツの更新タイムラグを最小化しつつ、無関係なキャッシュを維持できるため、CMSとCloudFrontの組み合わせでキャッシュ戦略に悩んでいた場面での活用が期待できます。

著者タグ・カテゴリタグでのInvalidation

4つの記事をS3にアップロードし、著者タグ・カテゴリタグでの選択的Invalidationを確認しました。

追加検証(TEST C / TEST D)

4つの記事ページに著者・カテゴリのタグを付与してアップロードします。

ファイル タグ
articles/001.html article:001, category:compute, author:suzuki
articles/002.html article:002, category:networking, author:suzuki
articles/003.html article:003, category:database, author:tanaka
articles/004.html article:004, category:storage, author:tanaka

TEST C: 著者タグで一括Invalidation(#author:suzuki

aws cloudfront create-invalidation --distribution-id "$DIST_ID" --paths "#author:suzuki"
記事 著者 Invalidation後
001 (Lambda入門) suzuki Miss
002 (CloudFront設計) suzuki Miss
003 (DynamoDB実践) tanaka Hit
004 (S3セキュリティ) tanaka Hit

suzukiの記事2件だけが無効化され、tanakaの記事はキャッシュヒットを維持しています。

TEST D: カテゴリタグで選択的Invalidation(#category:database

aws cloudfront create-invalidation --distribution-id "$DIST_ID" --paths "#category:database"
記事 カテゴリ Invalidation後
001 compute Hit
002 networking Hit
003 database Miss
004 storage Hit

同じ記事群に対して、著者軸でもカテゴリ軸でも、狙った記事だけを無効化できることを確認しました。

この記事をシェアする

関連記事