Claude Prompt Caching と Pre-warming 徹底解説 - 5分/1時間キャッシュと max_tokens=0 ウォームアップで TTFT を短縮する

Claude Prompt Caching と Pre-warming 徹底解説 - 5分/1時間キャッシュと max_tokens=0 ウォームアップで TTFT を短縮する

作成日:
更新日:

「LLM API は高い・遅い」を一気に解決する仕組みのひとつが プロンプトキャッシングです。Anthropic Claude はこれを早くから提供しており、最近では max_tokens: 0 による Pre-warming(事前ウォームアップ) という新しい手法も登場しました。本記事では、Claude のプロンプトキャッシングを 自動・明示の使い分け、料金、キャッシュ無効化、Pre-warming の運用パターンまで、公式ドキュメントを土台に整理します。

本記事は 2026年5月15日時点の公式ドキュメント(Prompt caching)をベースにしています。Claude Opus 4.7 / Sonnet 4.6 / Haiku 4.5 など、現行 Active モデル全てが対象です。

なぜ Prompt Caching が効くのか

LLM API への1リクエストは、ざっくり次のように分解できます。

入力トークンの読み込み(プリフィル)+ 出力トークンの生成(デコード)

長い system プロンプトや RAG コンテキスト、ツール定義を毎回送っていると、プリフィルだけで数百ms〜数秒かかります。Prompt Caching は 「同じプレフィックスは2回目以降スキップ」してくれる仕組みで、これにより:

  • TTFT(Time-To-First-Token)が大幅短縮: 数秒 → 数百msオーダーに
  • コスト削減: キャッシュ読み出しはベース入力単価の 10% だけ
  • レート制限の節約: キャッシュヒット分はレート制限の使用量から差し引かれる

「同じ system プロンプト + ツール定義」を毎リクエスト送るタイプのアプリ(チャットボット、コーディングアシスタント、エージェント、ナレッジベースQA)はほぼ全部、これを入れて損なしです。

仕組みの3ステップ

公式が書いている挙動はとてもシンプル。

  1. リクエスト送信時、システムは指定されたキャッシュブレークポイントまでのプロンプトプレフィックスが 既にキャッシュされているかを確認する
  2. あれば キャッシュ済みの内容を再利用し、その分の処理時間とコストを削減
  3. なければプロンプト全体を処理し、応答開始時にプレフィックスを キャッシュへ書き込む

Prompt caching references the entire prompt - tools, system, and messages (in that order) up to and including the block designated with cache_control.

つまりキャッシュ対象は toolssystemmessages の順で、cache_control を付けたブロックまでの一連のプレフィックス全体。途中だけ抜き出してキャッシュ、はできません。

デフォルトの キャッシュ寿命(TTL)は5分で、ヒットするたびに無償でリフレッシュされます。「5分じゃ足りない」場合のために 1時間キャッシュもオプションで提供されています(後述)。

料金体系

公式ドキュメント記載の主要モデルだけ抜粋します(USD / 100万トークン)。

モデル通常入力5分キャッシュ書き込み1時間キャッシュ書き込みキャッシュ読み込み出力
Claude Opus 4.7$5$6.25$10$0.50$25
Claude Opus 4.6$5$6.25$10$0.50$25
Claude Opus 4.5$5$6.25$10$0.50$25
Claude Opus 4.1$15$18.75$30$1.50$75
Claude Sonnet 4.6$3$3.75$6$0.30$15
Claude Sonnet 4.5$3$3.75$6$0.30$15
Claude Haiku 4.5$1$1.25$2$0.10$5

倍率にすると簡単で、

  • 5分書き込み: ベース×1.25
  • 1時間書き込み: ベース×2.0
  • キャッシュ読み込み: ベース×0.1

「1回書いて2回以上ヒットすれば元が取れる」のがざっくりした目安。実運用ではヒット率10倍以上は普通に出るので、ほぼ常にお得な計算になります。

サポートモデルと最小トークン

Prompt Caching は すべての Active な Claude モデルで利用可能。ただしモデルごとに 最小キャッシュトークン数があり、これを下回るプロンプトには cache_control を付けても 黙って無視されます(エラーにはならない)。

モデル最小キャッシュトークン
Claude Opus 4.7 / 4.6 / 4.54,096
Claude Haiku 4.54,096
Claude Sonnet 4.6 / 4.5 / Opus 4.11,024

「キャッシュされてるはずなのに cache_creation_input_tokenscache_read_input_tokens も両方 0」のときは、まずこの最小トークン数を満たしているかを疑うのが定石。少し足りないだけなら、意図的に system プロンプトを膨らませて閾値に到達させるのが推奨されています(読み込みは10%なので元が取れる)。

Automatic Caching: いちばん簡単な使い方

最も簡単に使う方法は、リクエストのトップレベルに cache_control を1つ置くだけ。マルチターンチャットなど、会話履歴が伸びていくケースに最適です。

Python: Automatic caching
import anthropic
 
client = anthropic.Anthropic()
 
response = client.messages.create(
    model="claude-opus-4-7",
    max_tokens=1024,
    cache_control={"type": "ephemeral"},
    system="You are a helpful assistant that remembers our conversation.",
    messages=[
        {"role": "user", "content": "My name is Alex. I work on machine learning."},
        {"role": "assistant", "content": "Nice to meet you, Alex!"},
        {"role": "user", "content": "What did I say I work on?"},
    ],
)
print(response.usage.model_dump_json())

Automatic Caching の挙動:

  • システムが 「最後のキャッシュ可能ブロック」にブレークポイントを自動で打つ
  • 会話が伸びるとブレークポイントも前進する
  • 同じプレフィックスで再リクエストすると、自動的にキャッシュヒット

「とりあえず効かせたい」「会話履歴がどんどん伸びる」用途ではほぼ常に正解。

Explicit Cache Breakpoints: きめ細かい制御

更新頻度が違う複数のセクションを別々にキャッシュしたいときは、cache_control個別のコンテンツブロックに直接置きます

Python: 明示ブレークポイントを system 末尾に打つ
response = client.messages.create(
    model="claude-opus-4-7",
    max_tokens=1024,
    system=[
        {"type": "text", "text": "あなたは法律文書を分析するAIアシスタントです。"},
        {
            "type": "text",
            "text": "次は契約書全文です: [50ページの契約書テキスト]",
            "cache_control": {"type": "ephemeral"},
        },
    ],
    messages=[{"role": "user", "content": "保証条項を要約して"}],
)

ブレークポイントは 最大4つまで使えます。ただし、料金ガイドが繰り返し強調する重要な原則:

Place cache_control on the last block whose prefix is identical across the requests you want to share a cache.

つまり「リクエスト間で 絶対に変わらないブロックの末尾」に置くのが鉄則。タイムスタンプやユーザー入力など、毎回変わるブロックに置くと 毎回キャッシュ書き込みだけ発生して読み込みが一度も起きない事故が起きます。

よくある事故

アンチパターン: タイムスタンプ含むブロックに breakpoint
[block 1-5] 静的な system context(変わらない)
[block 6]   "現在時刻: 2026-05-15 09:50:12 ..." + ユーザー入力
            ↑ ここに cache_control を置いてしまう

毎リクエストでタイムスタンプが変わる → ハッシュが毎回違う → 書き込み課金だけ発生して キャッシュ読み込みが一度もヒットしない

正しくは、block 5 の末尾に cache_control を置く。Automatic Caching も「最後のキャッシュ可能ブロック」に勝手に打つので、この構造では同じ罠にハマります。変動要素がプロンプト末尾にある場合は明示ブレークポイントを使うのが正解。

自動プレフィックス検索の仕組み(lookback)

ブレークポイントを1つだけ置いた場合でも、システムは 過去20ブロックぶん遡って過去のキャッシュ書き込みを探します。

  • ターン1: 10ブロック、ブレークポイントは block 10 → block 10 に書き込み
  • ターン2: 15ブロック、ブレークポイントは block 15 → block 15 にエントリなし → 後ろに5ブロック歩いて block 10 のヒット発見、新たに block 15 にも書き込み
  • ターン3: 35ブロック、ブレークポイントは block 35 → 20ブロック後ろまで(block 16 まで)チェック、block 15 のエントリは 1ブロック範囲外で見つからずミス

「会話が長く伸びる」ユースケースでは、lookback の20ブロック窓を超える前に、安全のため 2つ目のブレークポイントを中間に打っておくと事故を防げます。

キャッシュ無効化(Invalidation)

toolssystemmessages の階層を持っていて、変更が起きた階層から下が全部無効化されるルールです。

変更箇所toolssystemmessages影響
ツール定義(名前・説明・パラメータ)NGNGNG全キャッシュ無効化
Web Search トグルOKNGNGsystem 以下が無効化
Citations トグルOKNGNGsystem 以下が無効化
Speed setting(fast / 標準)OKNGNGsystem 以下が無効化
tool_choice 変更OKOKNGmessages のみ無効化
画像の追加/削除OKOKNGmessages のみ無効化
Extended Thinking パラメータOKOKNGmessages のみ無効化

特にハマりがちなのが、tool_choice の変更画像の有無。「ちょっとだけ実験で tool_choice を変えた」だけでメッセージキャッシュが消えるので、ABテストや実験コードでは要注意。

使用状況のトラッキング

レスポンスの usage フィールドで、キャッシュの利用状況が分かります。

usage の例
{
  "usage": {
    "input_tokens": 50,
    "cache_read_input_tokens": 100000,
    "cache_creation_input_tokens": 0,
    "output_tokens": 503
  }
}
  • cache_read_input_tokens: キャッシュからヒットして読み出したトークン数
  • cache_creation_input_tokens: 新たにキャッシュへ書き込んだトークン数
  • input_tokens: 最後のキャッシュブレークポイントより後ろの、キャッシュされていないトークン数

ハマりがちなポイントとして、input_tokens送信した入力全体ではなく「ブレークポイントより後ろ」のみを表しています。総入力は次の足し算:

total_input_tokens = cache_read_input_tokens + cache_creation_input_tokens + input_tokens

例: 200kのドキュメントをキャッシュ済み、新規50トークンの質問をすると、

  • cache_read_input_tokens: 200,000
  • cache_creation_input_tokens: 0
  • input_tokens: 50
  • 合計入力: 200,050 トークン

cache_read_input_tokens / total_input_tokens をモニタリングするだけで、キャッシュ戦略の効きが定量的に見えるようになります。

1時間キャッシュ(1-hour TTL)

5分が短いケースのために、1時間TTLもオプションで使えます。cache_controlttl を指定するだけ。

1時間キャッシュの指定
{
  "cache_control": {
    "type": "ephemeral",
    "ttl": "1h"
  }
}

書き込みコストは ベースの2倍(5分の 1.25倍 より高い)なので、無条件で1時間にすればよいわけではありません。公式の使い分け指針:

シナリオ推奨
同じ system プロンプトが5分以内に繰り返し使われる5分(リフレッシュ無料)
5分〜1時間の間隔でアクセスがあるエージェント1時間
ユーザーがしばらく返答しないチャット1時間
バッチで5分超〜1時間かかる処理1時間

5分と1時間は 同じリクエスト内に混在できますが、長いTTLが先に来る順序ルールがあります(1時間ブロック → 5分ブロックの順)。

Pre-warming the Cache(事前ウォームアップ)

ここからが本題。

なぜ事前ウォームアップが必要か

Prompt Caching の弱点は、「最初のリクエストはキャッシュミスでフルプリフィルが走る」こと。長い system プロンプトを抱えるアプリでは、ユーザーの最初のリクエストだけ TTFT が極端に遅くなる現象が起きます。

これを解決するのが max_tokens: 0 を使った Pre-warming。要するに 「ユーザーが来る前にキャッシュだけ温めておく」手法です。

仕組み

1. アプリ起動時 or 定期実行で max_tokens: 0 リクエストを送る
2. API はプリフィル(プロンプトの読み込み + キャッシュ書き込み)だけ実行
3. 出力生成はゼロでそのまま返す
4. レスポンスは content: [], stop_reason: "max_tokens"、usage はフル
5. ユーザーの実リクエストは、キャッシュヒットして即時応答開始

重要: ブレークポイントは「共有されるブロックの最後」に置く

Pre-warming のポイントは、cache_control を「実リクエストと共有される最後のブロック」(通常は system プロンプトやツール定義の末尾)に置くこと。プレースホルダの user メッセージに置いてしまうと、プレースホルダにキー付けされて実リクエストと一致せず、ヒットしません。

つまり Automatic Caching ではなく 明示ブレークポイントを使う必要があります。

Python での典型実装

公式が示している実装パターンをそのまま掲載。

Python: Pre-warming + 実リクエストの典型実装
import anthropic
 
client = anthropic.Anthropic()
 
SYSTEM_PROMPT = [
    {
        "type": "text",
        "text": "あなたは分散システムに精通したシニアソフトウェアエンジニアです...(長いプロンプト)",
        "cache_control": {"type": "ephemeral"},
    }
]
 
 
def prewarm_cache() -> None:
    """アプリ起動時 or 定期実行で呼ぶ。"""
    client.messages.create(
        model="claude-opus-4-7",
        max_tokens=0,
        system=SYSTEM_PROMPT,
        messages=[{"role": "user", "content": "warmup"}],
    )
 
 
def respond(user_message: str) -> anthropic.types.Message:
    """ユーザーからの実リクエスト。キャッシュヒットの恩恵を受ける。"""
    return client.messages.create(
        model="claude-opus-4-7",
        max_tokens=1024,
        system=SYSTEM_PROMPT,
        messages=[{"role": "user", "content": user_message}],
    )
 
 
prewarm_cache()
 
response = respond("二分探索木の実装方法を教えてください")
print(response.content[0].text)

課金の考え方

  • キャッシュ書き込み課金は通常通り発生cache_creation_input_tokens を見ると確認できる)
  • 出力トークンは0課金(実出力なし)
  • 5分キャッシュなら 5分以内に再ウォームアップ or 実リクエストを打たないと消える
  • 1時間キャッシュなら 1時間以内に同様

シンプルに言うと「ユーザーが来る前に書き込み課金だけ前倒しで支払う」という構造です。TTFT が体感1〜数秒短縮されることのビジネス価値を考えると、たいてい元は取れます。

Pre-warming の制約

max_tokens: 0 のリクエストは、出力を伴う以下の機能と 同時に使えませんinvalid_request_error で弾かれる)。

設定不可な理由
stream: true出力ゼロ前提なのでストリーミング不可
Extended Thinking(thinking.type: "enabled"thinking ブロック生成が必要
Structured Outputs(output_config.format構造化出力の生成が必要
tool_choice{"type": "tool", ...} または {"type": "any"}ツール呼び出し出力が必要
Message Batches API リクエスト内バッチ処理は TTFT 改善が無意味 + キャッシュも消える

max_tokens: 1 ワークアラウンドの置き換え

max_tokens: 0 が登場する前は max_tokens: 1 で似たことをやっていました。今後は max_tokens: 0 が公式推奨:

  • 1トークンの捨てる出力が出ない
  • 出力トークン課金が0になる
  • 「何のためのリクエストか」がコード上で明確

既存のウォームアップロジックがあるなら、10 に変えるだけで完了です。

ベストプラクティス

公式 + 実運用の知見を整理。

  1. マルチターンチャットはまず Automatic Caching: 何も考えずに cache_control をトップに置けばOK
  2. 末尾に変動要素があるなら明示ブレークポイント: タイムスタンプやユーザー入力の 直前cache_control を打つ
  3. キャッシュ可能なものはなるべく前に集める: tool 定義 → system → 例示 → ユーザー入力の順
  4. 1リクエストに breakpoint は最大4つ、料金は変わらない: 異なる更新頻度のコンテンツを独立にキャッシュしたいときに使う
  5. tool_choice と画像の有無は変えない: 軽い実験のつもりが messages キャッシュ全消しになる
  6. cache_read_input_tokens を必ずログる: ヒット率が分からなければ最適化もできない
  7. TTFTが重要なら Pre-warming: アプリ起動時 + cron で5分ごとに再ウォームアップ
  8. 長い間隔のあるエージェントは1時間TTL: 5分超の inactive 期間が想定されるなら最初から1時間で

ユースケース別の戦略

ユースケースキャッシュ戦略
カスタマーサポート Botsystem プロンプト + FAQ ベクター → Automatic Caching、5分TTL、Pre-warming
コーディングアシスタントプロジェクト概要 + コーディング規約 + サンプル → 明示ブレークポイント、1時間TTL
大規模ドキュメントQA(200kドキュメント)ドキュメント全文 → 明示ブレークポイント、1時間TTL、Pre-warming
エージェント(ツール多用)tools + system → 明示ブレークポイント、1時間TTL、状態は messages 末尾に
バッチで似たプロンプトを大量送信最初に1リクエスト送って1時間キャッシュ書き込み → 残りは並列で読み込み

ZDR とプライバシー

Prompt Caching(Automatic / Explicit どちらも)は ZDR(Zero Data Retention)対応で、Anthropic は raw のプロンプト・レスポンスを保存しません。

  • KV キャッシュ表現と暗号化ハッシュは メモリ上のみで保持
  • 5分(または1時間)の最低寿命後、速やかに削除
  • キャッシュは 組織間で完全に分離、2026年2月5日以降は ワークスペース単位でも分離(Claude API / Claude Platform on AWS / Microsoft Foundry beta)
  • Bedrock / Vertex AI は組織単位の分離のまま

「同じプロンプトを別組織と共有してしまう」「キャッシュされてた内容が漏洩する」といった懸念は構造的に発生しない設計です。

まとめ

  • Prompt Caching は toolssystemmessages の順でプレフィックスをキャッシュする仕組み
  • 料金は 書き込み×1.25 / 読み込み×0.1、ヒット2回で元が取れる計算
  • Automatic Caching は会話伸長型に最強、Explicit Breakpoints は変動要素がある構造に
  • cache_control「変わらないブロックの最後」に必ず置く(変動ブロックに置くと事故)
  • usage.cache_read_input_tokens を監視して効きを定量化
  • 5分/1時間の 2種類のTTLを使い分ける
  • Pre-warmingmax_tokens: 0)で 最初のユーザーリクエストの TTFT 遅延を消せる
  • Pre-warming は明示ブレークポイントが必須、stream / Extended Thinking / Structured Outputs / Batch とは併用不可

「とりあえず Automatic Caching を入れる」「効きが見えてきたら Pre-warming で TTFT を削る」という2段階の導入が、最も投資対効果が高いパスです。Claude を本番運用しているなら、いますぐ cache_read_input_tokens をダッシュボードに足して、ヒット率を見るところから始めてみてください。

参考リンク