自働化ラボ

Claude API2026/9/18更新:2026/9/18約10分で読めます

TTL戦略でPrompt Cachingコスト90%削減

Claude APIの入力トークン代が想定より膨らんでいるなら、原因はキャッシュ設計にあることが多いです。TTLの選び方とブレークポイントの配置次第で、同じワークロードでも請求額が数倍変わります。

結論から:TTLは「呼び出し間隔」で機械的に決める

キャッシュのTTLは好みではなく、呼び出し間隔から機械的に決まります。デフォルトの最小生存期間は5分です。この5分は、キャッシュが使われるたびにリフレッシュされます(Prompt caching公式ドキュメント)。5分では足りない場合、Anthropicは1時間のキャッシュTTLも提供しています(同ドキュメント)。

判断基準はシンプルです。呼び出し間隔が5分以内に収まるなら5分TTLを選びます。セッションの合間に5分以上の空白ができるなら1時間TTLを選びます。レビュー待ちや非同期承認、断続的なバッチ処理などが該当します。

損益分岐点も明確です。5分キャッシュは書き込みコストが1.25倍ですが、読み取りコストは標準入力の10%まで下がります(Prompt caching公式ドキュメント)。この構造では、1回読むだけでキャッシュなしより安くなります。1時間キャッシュは書き込みコストが2倍のため、元を取るにはもう少し読み取りが必要です。目安として、2回読んだ時点で損益が逆転します。

なぜ90%近い削減になるのか:公式料金表で数字を確認する

Prompt Cachingの値引きは、書き込みが高く読み取りが安いという非対称な料金体系から生まれます。新しいキャッシュエントリを作る処理コストが、書き込み価格に上乗せされているためです。

具体的な単価はAnthropic公式の料金ページで確認できます。Claude Sonnet 5の標準価格は、入力が100万トークンあたり2ドル、出力が10ドルです。この価格をもとに単価を計算すると、5分キャッシュの書き込みは2.50ドル(1.25倍)になります。1時間キャッシュの書き込みは4.00ドル(2倍)です。キャッシュ読み取りは0.20ドル(標準入力の10%)です。

この単価を使って試算します。対象は、3万トークンの固定コンテキスト(システムプロンプトとナレッジベース)です。これを1日1,000回呼び出すケースを考えます。1か月を30日とすると、月間の呼び出し回数は30,000回です。

キャッシュなしの場合、月間のトークン数は30,000回×30,000トークンで9億トークンになります。9億トークンを100万で割ると900です。900に2ドルをかけると、月額1,800ドルになります。

キャッシュありの場合を考えます。呼び出しが1日を通して続くため、5分TTLのキャッシュは読み取りのたびにリフレッシュされ続けます。1日1回だけ書き込みが発生し、残りは読み取りになると仮定します。

書き込み分は、30日×30,000トークンで90万トークンです。90万を100万で割って2.50ドルをかけると、2.25ドルになります。

読み取り分は、29,970回×30,000トークンで8億9,910万トークンです。8億9,910万を100万で割って0.20ドルをかけると、179.82ドルになります。

書き込み分と読み取り分を合計すると、月額182.07ドルになります。

削減率を計算します。(1,800-182.07)÷1,800を計算すると、約89.9%です。この数字は料金表の乗数をそのまま当てはめた試算です。実際のヒット率は呼び出しパターンによって変動します。

2026年のキャッシュ最適化パターン集

パターン1:高頻度エージェントループには5分TTL+自動キャッシュ

数秒〜数分間隔で連続してリクエストが飛ぶチャット型・エージェント型のワークロードでは、明示的な管理をしなくても恩恵を受けられます。自動キャッシュは、リクエストの最上位レベルに単一のcache_controlフィールドを追加するだけで有効になります(Prompt caching公式ドキュメント)。システムが最後にキャッシュ可能なブロックへ自動的にブレークポイントを適用し、会話が進むにつれて前方に移動させます。

import anthropic

client = anthropic.Anthropic()

response = client.messages.create(
    model="claude-sonnet-5",
    max_tokens=1024,
    system=[
        {
            "type": "text",
            "text": "あなたは社内FAQボットです。以下の社内規定を参照してください。\n\n" + long_policy_document,
            "cache_control": {"type": "ephemeral"}
        }
    ],
    messages=[
        {"role": "user", "content": "有給休暇の繰越上限は?"}
    ]
)

print(response.usage.cache_read_input_tokens)
print(response.usage.cache_creation_input_tokens)

パターン2:断続利用のセッションには1時間TTLを明示指定

レビュー待ちや承認フローを挟む業務アプリでは、5分TTLだと大半のリクエストでキャッシュが失効します。その結果、毎回フル書き込みになってしまいます。TTLを明示的に1時間へ延長するコードは次の通りです。

response = client.messages.create(
    model="claude-sonnet-5",
    max_tokens=1024,
    system=[
        {
            "type": "text",
            "text": long_policy_document,
            "cache_control": {"type": "ephemeral", "ttl": "1h"}
        }
    ],
    messages=conversation_history
)

TTLの基本的な選定基準そのものについては、以前公開したPrompt Cachingでコスト削減、TTL選択の実装ガイドでも整理しています。今回はその応用として、複数セクションを組み合わせる設計に踏み込みます。

パターン3:4つのブレークポイントでセクションごとに寿命を分ける

1リクエストで使えるブレークポイントには上限があります。1リクエストあたり最大4つのcache_controlブレークポイントを設定できます(Prompt caching公式ドキュメント)。この上限を使い、更新頻度の異なるセクションを独立してキャッシュするのが実務的なパターンです。

具体的には、ツール定義全体を1つ目のブレークポイントでキャッシュします。めったに変わらないシステムプロンプトの静的な指示を2つ目でキャッシュします。ナレッジベース文書を3つ目でキャッシュします。最後のユーザーメッセージに付ける4つ目で、会話履歴を段階的にキャッシュします。

この設計のメリットは明確です。ナレッジベースだけを更新しても、ツール定義や指示のキャッシュは壊れません。ブレークポイントを追加してもコスト自体は増加しません。実際にキャッシュされ読み取られた内容に基づいて課金される仕組みだからです(Prompt caching公式ドキュメント)。

パターン4:Batch APIと組み合わせて非同期処理をさらに削る

即時応答が不要な夜間バッチや大量分類処理では、キャッシュとBatch APIの割引を重ねられます。具体的な実装方法はBatch APIで大量データ処理を50%安くする方法で扱っているので、キャッシュ対象のシステムプロンプトをBatch APIのリクエストに載せる際の参考になります。

注意点:キャッシュが静かに壊れる3つの落とし穴

落とし穴1:ツール定義やモデルの変更が全体を無効化する。 会話の途中でツールやモデルを変更してはいけません。ツールは先頭位置にレンダリングされるため、追加・削除・並び替えはキャッシュ全体を無効化します。モデルの切り替えも同様です。動的な「モード」を実現したい場合は、ツールセット自体を切り替えず、モード遷移を記録する専用ツールを渡す設計が有効です。

落とし穴2:画像の有無や拡張思考の設定変更も無効化を引き起こす。 tool_choiceの変更や、プロンプト内での画像の有無の変化はキャッシュを無効化します。拡張思考のオン・オフや予算の変更も、以前キャッシュされたプロンプトの接頭辞を無効化します。日付やユーザーIDなどの動的な値をシステムプロンプトの先頭付近に置くのも同様に危険です。

落とし穴3:最小キャッシュ長はモデルによって異なり、無言で無視される。 キャッシュ可能な最小の接頭辞長はモデルに依存します。プロンプトが短すぎるとキャッシュされないことがありますが、その際にエラーは出ません。キャッシュトークン数がゼロのままなら、対応モデルとリージョン、上限を確認する必要があります(Claude Codeのプロンプトキャッシュ利用ガイド)。cache_creation_input_tokensが常にゼロになっていないかを定期的に確認する運用が欠かせません。

運用で見落としがちな2つの確認ポイント

  • cache_creation_input_tokensとcache_read_input_tokensを継続的に記録する:読み取り比率が想定より低い場合、TTL切れかプロンプトの動的な変更を疑います
  • ツール定義やモデルのデプロイ変更をログに残す:キャッシュが急に効かなくなったとき、直前のデプロイ履歴と突き合わせて原因を素早く特定できます
広告枠(準備中)

関連記事

参考にした一次ソース