Claude Code のプロンプトキャッシュ — CLAUDE.md も履歴も毎回送っているのに破綻しない理由
まとめ
- LLM の API はステートレスなので、Claude Code は CLAUDE.md も会話履歴も 毎ターン丸ごと送り直している 。省略はしていない。
- それでも料金・速度が破綻しないのは、先頭の安定した固まり(システムプロンプト+CLAUDE.md+過去の履歴)が プレフィックスキャッシュで約 0.1 倍のコストで再利用 されるから。
- キャッシュの TTL は固定ではなく 認証方法で変わる 。サブスク利用は 1 時間が自動で付き、API キー利用はデフォルト 5 分(環境変数で 1 時間にオプトイン)。
- キャッシュは料金と速度には効くが、 コンテキストウィンドウの使用量には効かない 。大きい CLAUDE.md は「安いが常に窓を圧迫する固定席」になる。
LLM の API はステートレス — だから毎回全部送っている
「Claude Code は前の会話を覚えているから、差分だけ送っているのだろう」と思いがちだが、そうではない。LLM の API は状態を持たない。毎回のリクエストで、システムプロンプト・ツール定義・CLAUDE.md・これまでの全会話履歴・ツール実行結果を まるごと再送信 して初めて応答が返る。
つまり 10 往復目の会話では、過去 9 往復ぶん+各種設定を全部詰め直して送っている。「積み重なった会話」の実体は、毎ターン先頭から組み立て直される 1 個の大きなプロンプトだ。
送信順は tools(ツール定義)→ system(システムプロンプト・CLAUDE.md)→ messages(会話履歴)で固定されている。この 先頭側=不変、末尾側=新規 という並びが、次に述べるキャッシュの効き方をそのまま決める。
破綻しない理由:プレフィックスキャッシュ
自分は最初、「10 往復の会話なら 5 往復ぶんくらいがキャッシュされる」みたいな 割合のイメージ を持っていた。でも実際は違う。プロンプトキャッシュは割合ではなく、 先頭から連続してどこまで同じか(プレフィックス) で効く。同じ先頭部分を再送した場合、そこは再計算せず激安で通せる。
トークンは 3 つの単価に分かれる(通常入力を 1.0 とした倍率)。
| 種別 | いつ発生するか | 倍率 |
|---|---|---|
| 通常入力 | 毎回フル処理されるぶん | 1.0 |
| キャッシュ書き込み(5 分 TTL) | その内容を初めて保存する時 | 1.25 |
| キャッシュ書き込み(1 時間 TTL) | 同上・1 時間版 | 2.0 |
| キャッシュ読み出し | 保存済みの内容を再利用する時 | 0.1 |
10 往復の会話を、毎ターン最新ターン末尾にキャッシュ境界を置いて進めた場合のイメージ:
| リクエスト | キャッシュ読み出し(約 0.1 倍) | 新規処理(フル料金) |
|---|---|---|
| 1 往復目 | なし | system + CLAUDE.md + 往復 1 |
| 2 往復目 | system + CLAUDE.md + 往復 1 | 往復 2 |
| 10 往復目 | system + CLAUDE.md + 往復 1〜9 | 往復 10 |
「毎回送信=毎回フル課金」ではない。 最初の 1 回だけ割増で預け、以降はずっと約 0.1 倍で引き出す 。往復が増えるほどキャッシュ読み出し部分が少しずつ伸びていくので、ファイルを大量に読んだ長いセッションでも、過去に読んだ内容が毎回フル課金されることはない。
TTL は認証方法で決まる(固定ではない)
ここは公式ドキュメントで確認できた事実で、直感と食い違いやすい。TTL は「常に 5 分」でも「常に 1 時間」でもなく、ログイン方法で変わる。
| 利用形態 | デフォルト TTL | 備考 |
|---|---|---|
| Claude 有料サブスク | 1 時間(自動) | プラン超過でクレジット消費中は 5 分に自動ダウングレード |
| API キー / サードパーティ(Bedrock 等) | 5 分 | ENABLE_PROMPT_CACHING_1H=1 で 1 時間にオプトイン |
| サブエージェント | 常に 5 分 | 1 時間はメイン会話のみに適用される |
制御用の環境変数もある(.claude/settings.json の env ブロックか環境変数で指定)。
| 環境変数 | 効果 |
|---|---|
ENABLE_PROMPT_CACHING_1H=1 | API キー利用時に 1 時間 TTL を有効化 |
FORCE_PROMPT_CACHING_5M=1 | 認証方法によらず 5 分に強制 |
DISABLE_PROMPT_CACHING=1 | キャッシュ全無効 |
対話ツールは「考え込む・離席する」で間が空きやすい。多少書き込みが高く(2 倍)ても長く生き残る 1 時間 TTL の方がトータルで有利、という判断がサブスク自動 1 時間の背景にある。
そして TTL タイマーは キャッシュにヒットするたびにリセット される。連続して操作していれば、5 分でも 1 時間でもキャッシュは温かいまま保たれる。逆に、長く放置して切れた後の最初のターンは、先頭から全部を再計算するため明らかに遅く・割高になる。
一方で、以下の操作は先頭側や履歴を作り替えるため キャッシュを無効化(再構築) する。
/modelによるモデル切り替え(キャッシュはモデル単位なので全崩壊)- effort レベルの変更
- MCP サーバーの接続 / 切断(ツール定義が変わると、その後ろ全部が無効)
/compact(会話履歴が要約に置き換わる=中盤が別物になる)- Claude Code 本体のアップグレード
注意したいのは、 通常のファイル編集ではキャッシュは切れない こと。作業中にファイルを何個編集してもキャッシュは有効なままで、崩れるのは上のような「プロンプトの構造そのものが変わる」操作だ。
キャッシュは「料金と速度」を助けるが「context」は助けない
最後に、混同しやすい点を分けておく。プロンプトキャッシュが効くのは 料金と処理速度 に対してだけ。 コンテキストウィンドウの使用量 には一切効かない。
キャッシュされていようがいまいが、CLAUDE.md も履歴も「送っている」ことに変わりはないので、そのトークン数は毎ターン context の窓を占有し続ける。したがって:
- 大きい CLAUDE.md や rules は「安いが常に席を取る固定席」になり、会話が長くなると context 圧迫の一因になる。
- 累計トークン消費は会話が延びるほど雪だるま式に増える(各ターンの入力が少しずつ増え、その積み重ねなので)。キャッシュはこの単価を約 0.1 倍に抑える仕組みであって、窓が埋まる問題そのものは解決しない。
窓が埋まる問題への対処は /compact か新規セッションで、料金・速度の問題への対処はキャッシュで、と住み分けて考えるのがよい。CLAUDE.md をどこに置くと何が読まれるかは別記事にまとめてある(Claude Code の CLAUDE.md 配置場所と優先順位)。
持ち帰り
- 「対話 AI が差分だけ送っている」という直感は捨てる。ステートレスな API では毎回全送信が基本で、効率化は差分送信ではなく プレフィックスキャッシュ で実現されている。この構造は Claude Code に限らず、この種のツールを評価するときの前提として持っておくとよい。
- ツールの「デフォルト値」は認証方法や契約形態で切り替わることがある。TTL のように挙動が変わる値は、記憶で断定せず一次情報(公式ドキュメント)で確認する。
- コスト最適化と context 最適化は別問題。キャッシュ(料金・速度)と compaction / セッション分割(窓の空き)を混同しないこと。