自働化ラボ

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

Prompt Cachingでコスト削減、TTL選択の実装ガイド

Claude APIの請求額が想定より高い、キャッシュを有効にしたのになぜか安くならない。原因の多くは、リクエストの間隔とキャッシュのTTL(有効期限)が噛み合っていないことにあります。TTLごとの書き込み単価と、構造化パターンを検算例つきで整理します。

結論から:リクエスト間隔が5分を超えるなら1時間TTLを検討する

Prompt Cachingの節約効果は、書き込み頻度と読み込み頻度のバランスで決まります。公式ドキュメントによると、キャッシュの読み込みは通常の入力価格の10%で済む一方、書き込みは5分TTLで1.25倍、1時間TTLでは2倍の単価がかかります(Pricing - Claude Platform Docs)。同ドキュメントは、5分TTLは1回の読み込みで元が取れ、1時間TTLは2回の読み込みで元が取れる設計だと説明しています。

リクエストが数秒〜数分おきに連続して届くワークロードなら、デフォルトの5分TTLのままで9割近いコスト削減が狙えます。一方、呼び出し間隔が5分を超えることが多い場合は注意が必要です。明示的に1時間TTLを指定しないと、キャッシュが期限切れを繰り返し、書き込みコストばかりがかさむことになります。

なぜTTLの選び方が重要なのか

Prompt Cachingは、システムプロンプトやツール定義、会話履歴など繰り返し送信される部分をcache_controlで指定し、次回以降の呼び出しで再利用する仕組みです。ephemeralタイプのcache_controlにttl: "1h"を指定すると、5分より長い1時間の拡張キャッシュを利用できます(Prompt caching公式ドキュメント)。

同ドキュメントは、5分より頻繁に使われるシステムプロンプトであれば、5分TTLを使い続けるべきだとも述べています。5分TTLは利用のたびに無償で更新されるためです。逆に言えば、呼び出し間隔が読めない、あるいは5分を超えることが多いワークロードでは、1時間TTLの方が総コストで有利になる場面があります。

なお、Claude Codeのユーザーコミュニティでは、2026年3月上旬ごろにキャッシュTTLのデフォルト挙動が変化したという報告があります。Anthropic公式のGitHubリポジトリに投稿されたIssueによると、投稿者が2026年1月11日から4月11日までの自身のセッションログを分析した結果、1時間TTLの書き込みが中心だった状態から5分TTLへ切り替わったように見えるタイミングが確認され、典型的な利用パターンでキャッシュ作成コストが20〜32%増加したと報告されています(GitHub Issue #46829)。この報告はユーザー個人による分析であり、Anthropicが公式に原因や仕様変更を認めたものではない点には注意が必要です。ただし、TTLの扱いが利用者の想定と食い違うとコストに直結しうることを示す事例として参考になります。

実装パターン:システムプロンプトを構造化してキャッシュヒット率を上げる

具体的な実装では、変化しない部分(システムプロンプト、ツール定義)を先頭に、変化する部分(ユーザーの直近メッセージ)を末尾に置くのが基本です。1時間TTLと5分TTLを同じリクエスト内で混在させることもできます。その場合、より長いTTLのキャッシュエントリを、より短いTTLのエントリより前に配置してください(Prompt caching公式ドキュメント)。

import anthropic

client = anthropic.Anthropic()

response = client.messages.create(
    model="claude-sonnet-5",
    max_tokens=1024,
    system=[
        {
            "type": "text",
            "text": STABLE_PERSONA_AND_RULES,  # 更新頻度が低い部分
            "cache_control": {"type": "ephemeral", "ttl": "1h"}
        },
        {
            "type": "text",
            "text": TOOL_DEFINITIONS_TEXT,  # ツール定義など中頻度で変わる部分
            "cache_control": {"type": "ephemeral"}  # 5分TTL(デフォルト)
        }
    ],
    messages=conversation_history + [
        {"role": "user", "content": latest_user_message}
    ]
)

usage = response.usage
print("cache_creation_input_tokens:", usage.cache_creation_input_tokens)
print("cache_read_input_tokens:", usage.cache_read_input_tokens)

cache_controlのブレークポイントを増やすこと自体で料金が上がることはありません。実際にキャッシュされ読み込まれた内容に応じて課金されます(Pricing - Claude Platform Docs)。そのため、変更頻度の異なるブロックごとに分割しておく方が柔軟に対応できます。CLAUDE.mdのようなプロジェクト共通指示を扱う場合は、CLAUDE.mdの指示が守られない時に見直すべき仕組みの構成の考え方も参考になります。

本ブログ記事の失敗時に今回のキャッシュ機能を採用しています。記事のレベルが判定基準に満たない場合は再度記事を生成しています。その際に再度プロンプトを与えるのではなく、キャッシュ機能を用いて指示を行なっています。そうすることでAPIの消費を抑えながら基準をクリアした質の高い記事を投稿することができます

注意点:間隔の空くワークロードで起きる逆転現象

具体的な数字で確認します。Claude Sonnet 5の価格は入力100万トークンあたり2ドル、出力100万トークンあたり10ドルで、期間限定価格ではなく標準価格として維持されています(Pricing - Claude Platform Docs)。この単価から、5分TTLの書き込みは1.25倍で2.5ドル、1時間TTLの書き込みは2倍で4ドル、読み込みは0.1倍で0.2ドル(いずれも100万トークンあたり)になります。この単価をもとに、10,000トークンのシステムプロンプトで試算します。

リクエスト間隔が短い場合(100回連続呼び出し)

キャッシュなしの費用は、100回×10,000トークン×2ドル/100万=2.00ドルです。 5分TTLキャッシュありの場合は、初回書き込み1回(10,000×2.5ドル/100万=0.025ドル)に加え、残り99回の読み込み(99×10,000×0.2ドル/100万=0.198ドル)で、合計0.223ドルになります。 削減率は(2.00-0.223)÷2.00で、約89%です。

リクエスト間隔が8分空く場合(6回呼び出し)

5分TTLでは間隔が常にTTLを超えるため、6回すべてがキャッシュミスとなり書き込みが発生します。合計は6×0.025ドル=0.15ドルで、キャッシュなしの0.12ドル(6×10,000×2ドル/100万)より約25%高くなります。 同じ条件で1時間TTLを使うと、間隔8分は1時間以内なのでキャッシュが維持されます。初回書き込み1回(10,000×4ドル/100万=0.04ドル)に加え、残り5回の読み込み(5×10,000×0.2ドル/100万=0.01ドル)で、合計0.05ドルです。キャッシュなしと比べて約58%の削減になります。

つまり、間隔が空くワークロードでデフォルトの5分TTLを使い続けると、キャッシュなしより高くつくことがあります。加えて、キャッシュ対象には最小トークン数の条件があります。公式ドキュメントによると、Claude Sonnet 5では最小1,024トークンを下回るブロックはcache_controlを指定しても静かにキャッシュされません(Prompt caching公式ドキュメント)。小さすぎるプロンプトを無理にキャッシュ設計に含めても効果は出ないため、対象の見極めが必要です。バッチ処理と組み合わせて呼び出し頻度を上げる方法はBatch APIで大量データ処理を50%安くする方法でも扱っています。間隔が空く処理をまとめて実行する設計も検討する価値があります。

結局どのTTLを選ぶべきか

  • リクエスト間隔が常に5分未満の高頻度ワークロード(チャットボット、連続バッチ処理など)は、デフォルトの5分TTLのままで問題なく、書き込みコストを抑えられます。
  • ユーザーの入力待ちや非同期処理を挟むワークロードで、呼び出し間隔が5分を超えることが多い場合は、明示的にttl: "1h"を指定することを推奨します。書き込み単価は上がりますが、総コストは下がる場面が多くなります。
  • 設計後はusage.cache_creation_input_tokensとusage.cache_read_input_tokensをログに残す運用が有効です。書き込みばかりで読み込みがほとんど発生していないブロックは、キャッシュ対象から外す判断も検討してください。
広告枠(準備中)

関連記事

参考にした一次ソース