Cost and latency
Prompt caching, batching and routing to cheaper models.
Create a free account Try part of it here
Why it matters
An AI feature that costs $0.02 a request is a rounding error in a demo. At 10,000 requests a day, it's $6,000 a month. The same few levers decide both the bill and the wait: how much text you send, how much you get back, which model reads it, and whether repeated text is cached. Teams often cut costs by more than half with no loss in quality, just by working through these levers in order.
What you'll be able to do
- Work out what a request costs from its usage fields, including cache reads and writes
- Structure prompts so prompt caching works, and know when it pays off
- Rank the other cost levers: model choice, output length, effort, batching, trimming input
- Explain what makes a reply slow and how to make it feel fast
What it covers
- Where the money goes
- Prompt caching
- Worked example: see the cache in the usage fields
- The other cost levers, in order
- The number finance asks for
Where the money goes
Every reply includes a usage section. It tells you exactly what you were charged for:
| Field | What it counts | Price on Claude Opus 5.5 (per million tokens) |
|---|---|---|
input_tokens | Input that wasn't read from or written to the cache | $4.00 |
cache_creation_input_tokens | Input written to the cache this time | $5.00 (1.25×) for the 5-minute cache |
cache_read_input_tokens | Input read from the cache | $0.20 |
output_tokens | Everything the model wrote, including thinking | $20.00 |
Two things stand out:
- Output costs five times as much as input.
- Cached input costs a twentieth of normal input on this model (around a tenth on most others).
Picture a support bot that sends the same 3,000-token help center with every question. It pays full price for the same text, over and over:
def cost(input_tokens, output_tokens, cache_read=0, cache_write=0): return (input_tokens * 4 + output_tokens * 20 + cache_read * 0.20 + cache_write * 5) / 1_000_000 per_day = 10_000 no_cache = cost(input_tokens=3_050, output_tokens=200) cached = cost(input_tokens=50, output_tokens=200, cache_read=3_000) print(f"without caching: ${no_cache:.4f} per request, ${no_cache * per_day:,.0f} per day") print(f"with caching: ${cached:.4f} per request, ${cached * per_day:,.0f} per day")
It prints $0.0162 per request ($162 a day) without caching, and $0.0048 per request ($48 a day) with it. The cost function multiplies each kind of token by its price per million, then divides by a million.
def cost(input_t, output_t): return (input_t * 4 + output_t * 20) / 1_000_000 print(cost(1000, 100))
Show the answer
0.006
1000 × 4 + 100 × 20 is 4,000 + 2,000 = 6,000, and 6,000 / 1,000,000 is 0.006: $0.004 for input plus $0.002 for output. Note how output costs more per token.
Prompt caching
Think of a teacher who photocopies the same worksheet for every class. It's quicker to keep a stack of copies ready than to write it out each time.
When the start of your prompt is the same across requests, the API can keep its processed form for a while and reuse it. That shared start might be instructions, a style guide, documents, tool definitions or the earlier turns of a conversation. You mark where the reusable part ends with cache_control:
"system": [{"type": "text", "text": HELP_CENTER_AND_RULES, "cache_control": {"type": "ephemeral"}}],
The rules that make it work:
- Stable first, changing last. The cache matches your prompt from the very beginning up to the marker, exactly, in the order tools, then system, then messages. A timestamp or user name near the top changes the text, so the cache misses every time.
- Writes cost a bit more, reads much less. A write costs 1.25× normal input for the default 5-minute lifetime (2× for the optional 1-hour lifetime). Each read restarts the timer.
- A minimum size. Starts shorter than the model's minimum (512 tokens on current models) aren't cached, and nothing warns you. Check
cache_creation_input_tokensto confirm. - Up to 4 markers per request, for parts that change at different rates. Tools might never change, a document might change daily, and the conversation changes every turn.
Caching also makes replies start sooner, because the model skips re-reading the cached part.
One extra write already costs more than it saves if nothing reads it. By two requests it has paid for itself, and 20 requests save about 84%.
Show the answer
4,000 tokens of policies first, then today's date and the customer's question
The cache matches from the very start. Put everything that never changes first, and anything that changes, like the date or the question, after it.
Worked example: see the cache in the usage fields
Put the whole help center in a cached system prompt, and ask two different questions. The second request reads the shared start from the cache.
import requests docs = requests.get("https://api.gradient.test/v1/docs").json()["data"] help_center = "\n\n".join(f"## {d['title']}\n{d['text']}" for d in docs) system = [{"type": "text", "text": "Answer customer questions using only this help center.\n\n" + help_center, "cache_control": {"type": "ephemeral"}}] for question in ["How long is the return window?", "Do gift cards expire?"]: response = requests.post("https://api.anthropic.com/v1/messages", headers={"x-api-key": "added-by-the-academy-server", "anthropic-version": "2026-10-21"}, json={"model": "claude-opus-5-5", "max_tokens": 200, "system": system, "messages": [{"role": "user", "content": question}]}, timeout=60).json() u = response["usage"] print(question, "| written:", u["cache_creation_input_tokens"], "| read:", u["cache_read_input_tokens"], "| uncached:", u["input_tokens"])
The first request writes the help center to the cache. The second reads it, and only the question is billed at the full input price. If someone sent the same start in the last few minutes, even your first request is a read. (The academy's simulator estimates tokens at about four characters each, so its counts are approximate.)
The other cost levers, in order
- Pick the cheapest model that passes your eval. Haiku 5.5 is 40 times cheaper than Opus 5.5 per token. Classifying, tagging and pulling out fields often work just as well on it. Route by task (the routing pattern), and prove it with an eval.
- Cap and shrink the output. Set
max_tokenssensibly. Ask for the format you need, such as "three bullets" or JSON, instead of essays. Use structured output. - Lower the effort for simple tasks. Less thinking means fewer output tokens and faster replies.
- Batch what can wait. The Message Batches API halves the price of every token, and the discount stacks with caching.
- Send less. Retrieve the five relevant chunks instead of the whole manual. Return small tool results. Drop old conversation turns you no longer need.
Measure before and after each change. A saving that costs quality will show up in the eval.
What makes replies slow
Two numbers matter:
- time to first token: how long before anything appears,
- total time: how long until the reply is finished.
The first grows with the length of the input and with thinking. The second depends mostly on how much the model writes, because output is produced one token at a time. So:
- Stream the reply, so people see text straight away (the streaming lesson). It doesn't make the answer finish sooner, but it makes it feel faster.
- Write less. Shorter outputs finish sooner.
- Use a smaller model or lower effort where quality allows.
- Cache long, repeated starts.
- Run independent calls at the same time instead of one after another.
For marketers: cost per request × requests per day × 30 is the number your finance team will ask for. Work it out before launch, with caching and model choice already applied.
The number finance asks for
With caching, the support bot costs $0.0048 per request. At 10,000 requests a day, over a 30-day month:
per_request = 0.0048 print(round(per_request * 10_000 * 30)) print(round(0.0162 * 10_000 * 30))
It prints 1440, then 4860: about $1,440 a month with caching, against $4,860 without. Same help center, same answers, roughly a third of the bill.
Show the answer
The time changes the first bytes of the prompt, so the cached start never matches
Move the changing date after the cached policies, or into the user message.
Show the answer
Stream the reply, so text starts appearing straight away
Streaming doesn't make the reply finish sooner, but people see text within a second or so instead of staring at a blank screen. A bigger model or more tokens would make it slower.
Practice what you just read
- 4 code examples you can edit and run
- a practice exercise that checks your code
- a 5-question quiz
- 5 review cards for spaced repetition
Try a quiz question
Which part of a prompt should come first so caching works?