[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"academy-blogs-en-1-1-all-golang-prompt-caching-claude-openai-all--*":3,"academy-blog-faqs-4gfjbiytxpe8j7c-en":91,"academy-blog-translations-4gfjbiytxpe8j7c":116},{"data":4,"page":90,"perPage":90,"totalItems":90,"totalPages":90},[5],{"alt":6,"collectionId":7,"collectionName":8,"content":9,"cover_image":10,"cover_image_l_url":11,"cover_image_m_url":12,"cover_image_path":13,"cover_image_s_url":14,"created":15,"created_by":16,"expand":17,"id":84,"keywords":85,"locale":55,"published_at":86,"scheduled_at":71,"school_blog":80,"short_description":87,"status":78,"title":88,"updated":89,"updated_by":16,"slug":81,"views":83},"Prompt Caching article cover: a laptop on a desk at night with a card comparing the system prompt cost of 100 requests on Claude Sonnet 5, about $2.00 without cache and about $0.22 with cache","sclblg987654321","school_blog_translations","\u003Cp>When developers who connect Claude or OpenAI to their Go services ask our team, \"Our API bill jumped this month. Should we switch to a cheaper model?\", our most common answer is \"Not yet. First look at what you send again on every request.\" Most systems resend the same long system prompt, the same tool definitions and the same reference documents on every call, and pay full price for them every single time.\u003C\u002Fp>\u003Cp>Both providers already have a fix for this. It is called Prompt Caching. But from what we have seen, plenty of systems turn it on and save nothing at all, because the cache never actually hits.\u003C\u002Fp>\u003Cp>This article answers one question: how do you shape requests from Go so the cache hits every time it should, and how do you prove from the numbers that it is really cutting your costs?\u003C\u002Fp>\u003Ch2>How Prompt Caching works\u003C\u002Fh2>\u003Cp>There is exactly one principle: \u003Cstrong>prefix match\u003C\u002Fstrong>. The provider keeps the processed result of the beginning of your prompt. If the next request starts with exactly the same content, character for character, that part does not have to be processed again and is billed at a much lower rate.\u003C\u002Fp>\u003Cp>\"Character for character\" is the most important phrase in this article. If anything earlier in the prompt differs by even one character, such as a timestamp, a user name or the order of fields in JSON, everything after that point is a miss.\u003C\u002Fp>\u003Cp>Claude builds the prefix in a fixed order: tools, then system, then messages (\u003Ca target=\"_blank\" rel=\"noopener noreferrer\" href=\"https:\u002F\u002Fplatform.claude.com\u002Fdocs\u002Fen\u002Fbuild-with-claude\u002Fprompt-caching\">Claude docs\u003C\u002Fa>). Change a tool definition even slightly and the cache for everything after it is gone.\u003C\u002Fp>\u003Ch2>How Claude and OpenAI differ\u003C\u002Fh2>\u003Cul>\u003Cli>\u003Cp>\u003Cstrong>Turning it on:\u003C\u002Fstrong> Claude needs you to add \u003Ccode>cache_control\u003C\u002Fcode> yourself, at the request level or on individual blocks, with up to 4 breakpoints. OpenAI caches automatically with no code changes, and also offers explicit breakpoints.\u003C\u002Fp>\u003C\u002Fli>\u003Cli>\u003Cp>\u003Cstrong>Minimum size:\u003C\u002Fstrong> On Claude it depends on the model, for example 1,024 tokens for Sonnet 5 and 512 tokens for Opus 5.5. On OpenAI it is 1,024 tokens for GPT-5.6 and later.\u003C\u002Fp>\u003C\u002Fli>\u003Cli>\u003Cp>\u003Cstrong>Cache write cost:\u003C\u002Fstrong> Claude charges 1.25x the input price for a 5-minute cache or 2x for a 1-hour cache. OpenAI charges nothing for models before GPT-5.6 and 1.25x from GPT-5.6 onward.\u003C\u002Fp>\u003C\u002Fli>\u003Cli>\u003Cp>\u003Cstrong>Cache read cost:\u003C\u002Fstrong> Claude charges 0.1x the input price on most models. OpenAI discounts cached input by up to about 90%, depending on the model.\u003C\u002Fp>\u003C\u002Fli>\u003Cli>\u003Cp>\u003Cstrong>Cache lifetime:\u003C\u002Fstrong> On Claude it is 5 minutes, refreshed for free every time the cache is used, with an optional 1-hour tier. On OpenAI the system manages it for you.\u003C\u002Fp>\u003C\u002Fli>\u003Cli>\u003Cp>\u003Cstrong>Rate limits:\u003C\u002Fstrong> On Claude, cache hits are not deducted from your rate limit. On OpenAI, cached tokens still count toward tokens-per-minute. If you keep hitting quotas, see \u003Ca target=\"_blank\" rel=\"noopener noreferrer\" href=\"https:\u002F\u002Fwww.superdevacademy.com\u002Fblogs\u002Fgolang-rate-limiting-ai-requests\">EP.164 Rate Limiting AI Requests\u003C\u002Fa>.\u003C\u002Fp>\u003C\u002Fli>\u003C\u002Ful>\u003Cp>Sources: \u003Ca target=\"_blank\" rel=\"noopener noreferrer\" href=\"https:\u002F\u002Fplatform.claude.com\u002Fdocs\u002Fen\u002Fbuild-with-claude\u002Fprompt-caching\">Claude docs\u003C\u002Fa> and \u003Ca target=\"_blank\" rel=\"noopener noreferrer\" href=\"https:\u002F\u002Fdevelopers.openai.com\u002Fapi\u002Fdocs\u002Fguides\u002Fprompt-caching\">OpenAI docs\u003C\u002Fa> (as of September 2026; multipliers and models change when new models ship. For an overview of the latest Claude models, see \u003Ca target=\"_blank\" rel=\"noopener noreferrer\" href=\"https:\u002F\u002Fwww.superdevacademy.com\u002Fblogs\u002Fclaude-opus-5-for-devs\">Claude Opus 5 for developers\u003C\u002Fa>).\u003C\u002Fp>\u003Cp>In short, OpenAI is easier because you get caching without doing anything, while Claude gives you finer control over exactly what gets cached. That control pays off when your prompt has several parts that change at different rates.\u003C\u002Fp>\u003Ch2>Enabling Claude Prompt Caching from Go\u003C\u002Fh2>\u003Cp>This example uses net\u002Fhttp and plain structs so you can see exactly what JSON goes over the wire. To compare with calling OpenAI through its SDK, see \u003Ca target=\"_blank\" rel=\"noopener noreferrer\" href=\"https:\u002F\u002Fwww.superdevacademy.com\u002Fblogs\u002Fgolang-openai-api-gpt4o-sdk-guide\">EP.144 Connecting to the OpenAI API with the Go SDK\u003C\u002Fa>.\u003C\u002Fp>\u003Cpre>\u003Ccode>package llm\n\nimport (\n\t\"bytes\"\n\t\"encoding\u002Fjson\"\n\t\"fmt\"\n\t\"net\u002Fhttp\"\n\t\"os\"\n)\n\ntype CacheControl struct {\n\tType string `json:\"type\"`          \u002F\u002F \"ephemeral\"\n\tTTL  string `json:\"ttl,omitempty\"` \u002F\u002F \"\" = 5 minutes, \"1h\" = 1 hour\n}\n\ntype TextBlock struct {\n\tType         string        `json:\"type\"`\n\tText         string        `json:\"text\"`\n\tCacheControl *CacheControl `json:\"cache_control,omitempty\"`\n}\n\ntype Message struct {\n\tRole    string `json:\"role\"`\n\tContent string `json:\"content\"`\n}\n\ntype Request struct {\n\tModel     string      `json:\"model\"`\n\tMaxTokens int         `json:\"max_tokens\"`\n\tSystem    []TextBlock `json:\"system\"`\n\tMessages  []Message   `json:\"messages\"`\n}\n\ntype Usage struct {\n\tInputTokens              int `json:\"input_tokens\"`\n\tCacheCreationInputTokens int `json:\"cache_creation_input_tokens\"`\n\tCacheReadInputTokens     int `json:\"cache_read_input_tokens\"`\n\tOutputTokens             int `json:\"output_tokens\"`\n}\n\ntype Response struct {\n\tUsage Usage `json:\"usage\"`\n}\n\n\u002F\u002F systemPrompt must be static: no timestamps, user names or anything that changes per request\nfunc Ask(systemPrompt, question string) (*Response, error) {\n\tbody := Request{\n\t\tModel:     \"claude-sonnet-5\",\n\t\tMaxTokens: 1024,\n\t\tSystem: []TextBlock{{\n\t\t\tType:         \"text\",\n\t\t\tText:         systemPrompt,\n\t\t\tCacheControl: &amp;CacheControl{Type: \"ephemeral\"}, \u002F\u002F breakpoint at the end of the static part\n\t\t}},\n\t\tMessages: []Message{{Role: \"user\", Content: question}}, \u002F\u002F the changing part comes after the breakpoint\n\t}\n\n\tb, err := json.Marshal(body)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\treq, err := http.NewRequest(\"POST\", \"https:\u002F\u002Fapi.anthropic.com\u002Fv1\u002Fmessages\", bytes.NewReader(b))\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\treq.Header.Set(\"x-api-key\", os.Getenv(\"ANTHROPIC_API_KEY\"))\n\treq.Header.Set(\"anthropic-version\", \"2023-06-01\")\n\treq.Header.Set(\"content-type\", \"application\u002Fjson\")\n\n\tres, err := http.DefaultClient.Do(req)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tdefer res.Body.Close()\n\tif res.StatusCode != http.StatusOK {\n\t\treturn nil, fmt.Errorf(\"anthropic: status %d\", res.StatusCode)\n\t}\n\n\tvar out Response\n\treturn &amp;out, json.NewDecoder(res.Body).Decode(&amp;out)\n}\u003C\u002Fcode>\u003C\u002Fpre>\u003Cp>The heart of this code is a single line: CacheControl must sit on \u003Cstrong>the last block that is identical on every request\u003C\u002Fstrong>, never on a block that changes each time.\u003C\u002Fp>\u003Ch3>Reading the numbers\u003C\u002Fh3>\u003Cp>The usage object in the response has three values to watch.\u003C\u002Fp>\u003Cul>\u003Cli>\u003Cp>\u003Ccode>cache_creation_input_tokens\u003C\u002Fcode> is the number of tokens just written to the cache in this request.\u003C\u002Fp>\u003C\u002Fli>\u003Cli>\u003Cp>\u003Ccode>cache_read_input_tokens\u003C\u002Fcode> is the number of tokens read from the cache in this request.\u003C\u002Fp>\u003C\u002Fli>\u003Cli>\u003Cp>\u003Ccode>input_tokens\u003C\u002Fcode> is only the tokens after the last cache breakpoint, not your total input.\u003C\u002Fp>\u003C\u002Fli>\u003C\u002Ful>\u003Cp>Total input is the sum of all three. If cache_creation_input_tokens and cache_read_input_tokens are both 0, nothing was cached. The usual cause is a prompt shorter than the model's minimum; the API silently skips caching without returning an error (\u003Ca target=\"_blank\" rel=\"noopener noreferrer\" href=\"https:\u002F\u002Fplatform.claude.com\u002Fdocs\u002Fen\u002Fbuild-with-claude\u002Fprompt-caching\">Claude docs\u003C\u002Fa>).\u003C\u002Fp>\u003Cp>On OpenAI, read \u003Ccode>cached_tokens\u003C\u002Fcode> from usage.prompt_tokens_details in Chat Completions or usage.input_tokens_details in the Responses API. GPT-5.6 and later also report \u003Ccode>cache_write_tokens\u003C\u002Fcode> (\u003Ca target=\"_blank\" rel=\"noopener noreferrer\" href=\"https:\u002F\u002Fdevelopers.openai.com\u002Fapi\u002Fdocs\u002Fguides\u002Fprompt-caching?prompt-cache-api=chat-completions\">OpenAI docs\u003C\u002Fa>).\u003C\u002Fp>\u003Ch2>Is it worth it? Working it out from real prices\u003C\u002Fh2>\u003Cp>Take Claude Sonnet 5 prices per million tokens from the docs as of September 2026: $2 for regular input, $2.50 for a 5-minute cache write and $0.20 for a cache read.\u003C\u002Fp>\u003Cp>Assume a 10,000-token system prompt and 100 requests arriving often enough that the cache never expires.\u003C\u002Fp>\u003Cul>\u003Cli>\u003Cp>\u003Cstrong>Without cache:\u003C\u002Fstrong> 100 x 10,000 x $2 \u002F 1,000,000 = about $2.00\u003C\u002Fp>\u003C\u002Fli>\u003Cli>\u003Cp>\u003Cstrong>With cache:\u003C\u002Fstrong> one write at 10,000 x $2.50 \u002F 1,000,000 = $0.025, plus 99 reads at 99 x 10,000 x $0.20 \u002F 1,000,000 = $0.198, for a total of about $0.22\u003C\u002Fp>\u003C\u002Fli>\u003C\u002Ful>\u003Cp>This covers only the system prompt. It excludes user questions and output, which cost the same either way, and it assumes every request hits. A real system will save less, in proportion to its hit rate.\u003C\u002Fp>\u003Cp>Break-even comes very quickly: one write plus one read costs 1.25 + 0.1 = 1.35x, while two uncached requests cost 2x. A single hit already pays for the write. The function below calculates this from real usage data and plugs straight into the cost-logging setup from \u003Ca target=\"_blank\" rel=\"noopener noreferrer\" href=\"https:\u002F\u002Fwww.superdevacademy.com\u002Fblogs\u002Fgolang-the-series-ep149-token-management-api-cost-control\">EP.149 Token Management\u003C\u002Fa>.\u003C\u002Fp>\u003Cpre>\u003Ccode>\u002F\u002F Price per million tokens (USD). Pull it from the pricing page for the model you use; do not hardcode it forever.\ntype Price struct {\n\tInput, CacheWrite5m, CacheRead float64\n}\n\nfunc CostUSD(u Usage, p Price) (withCache, withoutCache float64) {\n\tconst m = 1_000_000.0\n\twithCache = float64(u.InputTokens)*p.Input\u002Fm +\n\t\tfloat64(u.CacheCreationInputTokens)*p.CacheWrite5m\u002Fm +\n\t\tfloat64(u.CacheReadInputTokens)*p.CacheRead\u002Fm\n\n\ttotal := u.InputTokens + u.CacheCreationInputTokens + u.CacheReadInputTokens\n\twithoutCache = float64(total) * p.Input \u002F m\n\treturn\n}\u003C\u002Fcode>\u003C\u002Fpre>\u003Cp>This function covers input only and assumes the 5-minute cache. If you use the 1-hour cache, price cache_creation.ephemeral_1h_input_tokens separately.\u003C\u002Fp>\u003Cp>You get speed as well as savings. OpenAI's own tests found that short 1,024-token prompts got about 7% faster, while prompts of 150,000 tokens or more saw roughly 67% faster time-to-first-token (\u003Ca target=\"_blank\" rel=\"noopener noreferrer\" href=\"https:\u002F\u002Fdevelopers.openai.com\u002Fcookbook\u002Fexamples\u002Fprompt_caching_201\">OpenAI Cookbook\u003C\u002Fa>). The longer the prompt, the bigger the difference.\u003C\u002Fp>\u003Ch2>Can I just put cache_control on every request?\u003C\u002Fh2>\u003Cp>You can, and Claude has an automatic caching mode: set cache_control once at the request level and the API moves the breakpoint to the last block for you. It is a great fit for multi-turn chats whose history keeps growing.\u003C\u002Fp>\u003Cp>But if the last block changes every time, for example because you append the current time or per-request context to the end of the prompt, the API writes a new cache entry on every request and never reads one. You pay a 25% write premium on every request and get nothing back (\u003Ca target=\"_blank\" rel=\"noopener noreferrer\" href=\"https:\u002F\u002Fplatform.claude.com\u002Fdocs\u002Fen\u002Fbuild-with-claude\u002Fprompt-caching\">Claude docs\u003C\u002Fa>). In that case, use an explicit block-level breakpoint placed at the end of the static part instead.\u003C\u002Fp>\u003Cp>The easy rule to remember: what never changes goes first, what changes goes last. A safe order is tools, core instructions, reference documents, chat history, and finally the latest question.\u003C\u002Fp>\u003Ch2>A trap Go developers need to know about\u003C\u002Fh2>\u003Cp>The Claude docs warn that some languages, Go among them, may randomize key order when converting to JSON, which breaks cache matching.\u003C\u002Fp>\u003Cp>It is worth being precise here. Go's encoding\u002Fjson always sorts map keys in json.Marshal, so that path is safe. The real risks are elsewhere.\u003C\u002Fp>\u003Cul>\u003Cli>\u003Cp>\u003Cstrong>Building a prompt by ranging over a map.\u003C\u002Fstrong> Map iteration order in Go is randomized, so the resulting text comes out in a different order each time. Use a slice with a fixed order instead.\u003C\u002Fp>\u003C\u002Fli>\u003Cli>\u003Cp>\u003Cstrong>Using another JSON library\u003C\u002Fstrong> that does not guarantee key order.\u003C\u002Fp>\u003C\u002Fli>\u003Cli>\u003Cp>\u003Cstrong>tool_use input you store and send back\u003C\u002Fstrong>, if you convert it through a map and reassemble it without sorting the keys.\u003C\u002Fp>\u003C\u002Fli>\u003C\u002Ful>\u003Cp>The safest approach is to use structs, as in the example above, because struct field order is always fixed.\u003C\u002Fp>\u003Ch2>Does caching make the AI give the same answer, or use stale data?\u003C\u002Fh2>\u003Cp>This is worth asking before you turn it on. The answer is no. Prompt caching has no effect on output generation; the response is identical to what you would get without caching (\u003Ca target=\"_blank\" rel=\"noopener noreferrer\" href=\"https:\u002F\u002Fplatform.claude.com\u002Fdocs\u002Fen\u002Fbuild-with-claude\u002Fprompt-caching\">Claude docs\u003C\u002Fa>). What the cache stores is the processed input, not the answer.\u003C\u002Fp>\u003Cp>Caching does not keep your data fresh either, though. If the reference documents in your prompt are out of date, answers will still be based on the old content. Systems that need current data still need their own way to update that content, and must accept that every update causes one miss for that section and everything after it.\u003C\u002Fp>\u003Cp>Teams also often ask about security. Claude caches are isolated between organizations, and on the Claude API also between workspaces. OpenAI caches are isolated per organization. Users in different organizations never share a cache.\u003C\u002Fp>\u003Cdiv data-type=\"horizontalRule\">\u003Chr>\u003C\u002Fdiv>\u003Ch2>Summary: turning the cache on is not enough, you have to design for hits\u003C\u002Fh2>\u003Cp>The straight answer:\u003C\u002Fp>\u003Cp>\u003Cstrong>Do it now\u003C\u002Fstrong> if your system has a system prompt, tool definitions or reference documents longer than your model's minimum, and requests arrive often enough that the cache does not expire. A single hit already pays for the write.\u003C\u002Fp>\u003Cp>\u003Cstrong>No need to rush\u003C\u002Fstrong> if your prompts are shorter than the minimum, or every request is completely different. Caching will barely help there.\u003C\u002Fp>\u003Cp>If you start today, start with one thing: add cache_read_input_tokens or cached_tokens to the logs you already have and watch for a day how often you really hit. That number will tell you what to move to the front of your prompt and where you are still leaking.\u003C\u002Fp>","cover_cover_33su203913.webp","https:\u002F\u002Ftwsme-r2.tumwebsme.com\u002Fsclblg987654321\u002F3cmygfyr7pwzqxe\u002Fl\u002Fcover_cover_33su203913.webp","https:\u002F\u002Ftwsme-r2.tumwebsme.com\u002Fsclblg987654321\u002F3cmygfyr7pwzqxe\u002Fm\u002Fcover_cover_33su203913.webp","https:\u002F\u002Ftwsme-r2.tumwebsme.com\u002Fsclblg987654321\u002F3cmygfyr7pwzqxe\u002Fcover_cover_33su203913.webp","https:\u002F\u002Ftwsme-r2.tumwebsme.com\u002Fsclblg987654321\u002F3cmygfyr7pwzqxe\u002Fs\u002Fcover_cover_33su203913.webp","2026-09-24 06:31:46.813Z","qym0hub9bm27ns3",{"keywords":18,"locale":49,"school_blog":59},[19,25,31,35,40,44],{"collectionId":20,"collectionName":21,"created":22,"created_by":16,"id":23,"name":24,"updated":22,"updated_by":16},"sclkey987654321","school_keywords","2026-09-24 05:18:17.047Z","pvi8p900bsnv9gz","Prompt Caching",{"collectionId":20,"collectionName":21,"created":26,"created_by":27,"id":28,"name":29,"updated":30,"updated_by":27},"2026-03-04 08:20:14.253Z","76qprkevbgfdps8","ah6lvy4x8qe08l5","Golang","2026-06-07 06:45:08.193Z",{"collectionId":20,"collectionName":21,"created":32,"created_by":27,"id":33,"name":34,"updated":32,"updated_by":27},"2026-06-11 16:54:41.946Z","015roiohb99sg77","Claude API",{"collectionId":20,"collectionName":21,"created":36,"created_by":27,"id":37,"name":38,"updated":39,"updated_by":27},"2026-05-11 06:33:36.935Z","xp9ljhapsv79n2f","OpenAI API","2026-06-07 06:49:12.039Z",{"collectionId":20,"collectionName":21,"created":41,"created_by":27,"id":42,"name":43,"updated":41,"updated_by":27},"2026-06-11 16:14:34.250Z","01ajl5eq1joxocg","LLM",{"collectionId":20,"collectionName":21,"created":45,"created_by":27,"id":46,"name":47,"updated":48,"updated_by":27},"2026-03-04 08:44:53.062Z","puutdnxuitnxxgq","Backend","2026-06-07 06:46:40.599Z",{"code":50,"collectionId":51,"collectionName":52,"created":53,"flag":54,"id":55,"is_default":56,"label":57,"updated":58},"en","pbc_1989393366","locales","2026-01-22 11:00:02.726Z","twemoji:flag-united-states","qv9c1llfov2d88z",false,"English","2026-04-10 15:42:46.825Z",{"category":60,"collectionId":61,"collectionName":62,"created":63,"expand":64,"id":80,"slug":81,"updated":82,"views":83},"spm4l1k5bgmhmmt","pbc_2105096300","school_blogs","2026-09-24 05:18:17.049Z",{"category":65},{"blogIds":66,"collectionId":67,"collectionName":68,"created":69,"created_by":27,"id":60,"image":70,"image_alt":71,"image_path":72,"image_s_url":73,"label":74,"name":75,"priority":76,"publish_at":77,"scheduled_at":71,"status":78,"updated":79,"updated_by":27},[],"sclcatblg987654321","school_category_blogs","2026-03-04 08:31:18.590Z","50hyjr6os45_ayazwr5gq7_tqzz9l5y5w.webp","","https:\u002F\u002Ftwsme-r2.tumwebsme.com\u002Fsclcatblg987654321\u002Fspm4l1k5bgmhmmt\u002F50hyjr6os45_ayazwr5gq7_tqzz9l5y5w.webp","https:\u002F\u002Ftwsme-r2.tumwebsme.com\u002Fsclcatblg987654321\u002Fspm4l1k5bgmhmmt\u002Fs\u002F50hyjr6os45_ayazwr5gq7_tqzz9l5y5w.webp",{"en":75,"th":75},"Knowledge",0,"2026-03-18 02:25:41.222Z","published","2026-08-18 14:49:11.737Z","4gfjbiytxpe8j7c","golang-prompt-caching-claude-openai","2026-09-24 10:42:49.775Z",119,"3cmygfyr7pwzqxe",[23,28,33,37,42,46],"2026-09-24 06:42:33.341Z","Prompt Caching can cut the input cost of the Claude and OpenAI APIs dramatically, but only when the cache actually hits. Learn how to shape requests from Go so they hit, and how to measure the savings from the numbers in the response.","What Is Prompt Caching? Cut Claude\u002FOpenAI API Costs in Production with Go","2026-09-24 06:42:42.240Z",1,[92,96,100,104,108,112],{"answer":93,"id":94,"question":95},"Claude, and OpenAI from GPT-5.6 onward, charge more than the regular input price to write to the cache. If an entry is written but never read before it expires, for example because users pause longer than the cache lifetime or the breakpoint sits on a block that changes every time, caching costs you extra instead of saving money.","hw5y2lqsdg40d7t","When does Prompt Caching cost more instead of less?",{"answer":97,"id":98,"question":99},"If requests arrive more often than every 5 minutes, the 5-minute cache is enough because it refreshes for free each time it is used. The 1-hour cache suits cases where users may pause longer than 5 minutes but less than an hour, such as long chats or agents with slow steps. It costs more to write: 2x the input price versus 1.25x.","wpxewy45ag0aepc","Should I choose the 5-minute or the 1-hour cache?",{"answer":101,"id":102,"question":103},"Because OpenAI counts cache hits in 128-token increments once the minimum is met, so the number is usually slightly below the length of your static prefix. That is normal.","qctjix3cnbttkgp","Why doesn't OpenAI's cached_tokens exactly match my static prompt length?",{"answer":105,"id":106,"question":107},"On Claude, yes, and the cache price multipliers stack with the Batch API discount.","mmsht33bfzxjjbh","Can I use Prompt Caching with the Batch API?",{"answer":109,"id":110,"question":111},"There are three common causes: the prompt is shorter than the model's minimum, so caching is skipped without an error; the next request arrives after the cache has expired; or something before the breakpoint changes every time, such as a timestamp or text assembled by ranging over a Go map.","mlmwpp4ju81bi9j","Why is cache_read_input_tokens still 0 after I set cache_control?",{"answer":113,"id":114,"question":115},"It works on every active Claude model, with both automatic caching and explicit breakpoints. The minimum cacheable length varies by model, for example 512 tokens for Opus 5.5, 1,024 tokens for Sonnet 5 and 4,096 tokens for Haiku 4.5. Shorter prompts are not cached and no error is returned.","bfh4patsf2o13n8","Which Claude models support Prompt Caching?",{"th":81,"en":81}]