Rubric
Contents — domains, guide and mocks

Optimising tokens, latency and cost

CCAR-P 4.513 min read · checked 21 September 2026

Task statementOptimize token usage, latency, and cost-performance trade-offs

The main levers

Cost · latency · qualitymeasured per successful task
  • Model choiceHaiku, Sonnet, Opus, routing
  • Effortthinking and output volume
  • Prompt cachingrepeated prefix at 0.1×
  • Batch API50% off, not real-time
  • Output lengthconcise asks, max_tokens
  • Input sizetrim context and tools
Every lever trades something. Caching and batching save money without changing the model's output; the others can change quality, so they must be re-checked against your evals.

Where the money goes in one request

A request is billed on four kinds of token, reported in the response's usage block: uncached input (input_tokens), tokens written to the cache (cache_creation_input_tokens), tokens read from the cache (cache_read_input_tokens) and output (output_tokens). The prompt-caching docs point out a trap: input_tokens counts only the tokens after the last cache breakpoint, so total input is the sum of all three input fields.

Model (Sep 2026)Input / MTokOutput / MTokCache readBatch
Claude Haiku 4.5$1$5$0.1050% off input and output
Claude Sonnet 5$2$10$0.2050% off input and output
Claude Opus 5$5$25$0.5050% off input and output

Two ratios drive most decisions. Output costs five times input on every model in the table, so a verbose answer is often the biggest line on the bill. And a cache read costs a tenth of a normal input token. Prices change — they're shown here to practise the arithmetic, and the pricing page is the source of truth. One more caution from that page: Claude 4.7 and later models use a newer tokenizer that produces roughly 30% more tokens for the same text, so compare models on measured cost per task, not on list price. The token-counting endpoint, which is free to call, counts a prompt under the tokenizer of the model you name.

Prompt caching: pay once for the part that repeats

Caching stores a processed prompt prefix so later requests that start with the same content read it back cheaply and faster. The prefix is built in a fixed order — tools, then system, then messages — and any change invalidates everything after it. The rules that matter for design:

  • Stable content first, variable content last. Anything that changes per request — a timestamp, the user's name — must come after the breakpoint.
  • Automatic or explicit. A single top-level cache_control lets the API place and advance the breakpoint as a conversation grows; explicit breakpoints (up to 4 per request) suit sections that change at different rates.
  • Minimum length. Prompts shorter than the model's minimum aren't cached, and no error is returned — for example 1,024 tokens on Claude Sonnet 5 and 4,096 on Claude Haiku 4.5.
  • Lifetime. The default cache lives 5 minutes; a 1-hour option costs more to write.

Why a cache never hits

0% cache hitstext

system:
  "Current time: 09:41:07.
   User: Priya (Gold tier).
   [5,800 tokens of policy,
    tone rules and examples]"
  cache_control ← here

messages: [question]

Hits on every repeattext

system:
  "[5,800 tokens of policy,
    tone rules and examples]"
  cache_control ← here

messages:
  "Current time: 09:41:07.
   User: Priya (Gold tier).
   [question]"
On the left the first line changes every request, so every prefix is new. On the right the long, stable part comes first and the breakpoint sits at its end.

The break-even is quick. A 5-minute cache write costs 1.25× normal input and each read 0.1×, so the pricing page notes it pays off after one read; the 1-hour cache write costs 2× and pays off after two reads.

Cost per request under three set-ups (Claude Sonnet 5 prices)python
IN, OUT, READ = 2.00, 10.00, 0.20          # USD per million tokens

def cost(prefix, fresh, out, cached=False, batch=False):
    prefix_rate = READ if cached else IN       # warm cache assumed
    usd = (prefix * prefix_rate + fresh * IN + out * OUT) / 1e6
    return usd * (0.5 if batch else 1.0)       # batch halves every rate

# 6,000-token stable prefix, 300 fresh tokens, 400 output tokens
print(cost(6000, 300, 400))                # 0.0166  baseline
print(cost(6000, 300, 400, cached=True))   # 0.0058  -65%
print(cost(6000, 300, 150, cached=True))   # 0.0033  shorter answers too

Look at the second line. Once the prefix is cached, the 400 output tokens ($0.004) are about 70% of the remaining cost. The next lever isn't more caching; it is answer length.

The other levers, and what each one costs you

LeverSavesPrice you payUse when
Smaller model (e.g. Haiku 4.5)Cost and latencyCapability on hard casesSimple, high-volume tasks that pass your evals
Lower effortOutput and thinking tokens, timeSome depth on hard problemsRoutine work on a model that supports effort
Batch API50% on input and outputAsynchronous; most batches under 1 hour, up to 24 hoursNobody is waiting for the answer
Shorter outputOutput tokens, timeDetailAnswers are longer than users need
Smaller inputInput tokens, timeRisk of dropping needed contextUnused tools, whole documents where excerpts would do
StreamingPerceived latency (time to first token)Nothing on costA person watches the answer appear
Fast mode (preview)Output speed on Opus 5 / 4.8Premium price; not in batchLatency matters more than cost on the top model

Effort. Effort is set with output_config.effort and defaults to high. It affects all output — text, tool calls and thinking — and lower levels make fewer, terser tool calls. It isn't available on every model (Claude Haiku 4.5 is not on the supported list). Anthropic's guide to cost and intelligence goes further: sweep effort on your current model before trying multi-model set-ups, because it beats most of them.

Batch. The Message Batches API halves the price of every token and takes up to 100,000 requests or 256 MB per batch. Results arrive when the whole batch ends or after 24 hours, whichever is first; unfinished requests expire and aren't billed. Discounts stack with caching, but cache hits inside a batch are best-effort, and the docs suggest the 1-hour cache for shared context because batches can outlast 5 minutes.

Output length. Ask for brevity in the prompt; the latency guide notes that sentence or paragraph limits work better than word counts, because models count tokens, not words. max_tokens is a hard cap, not a length request: a response that hits it is cut off mid-sentence. On models with adaptive thinking, max_tokens also covers thinking, and thinking tokens bill as output even when the thinking text isn't returned.

Model routing. Anthropic's guide describes two multi-model patterns: a cheaper executor that escalates hard decisions to a stronger advisor, and a frontier orchestrator that fans bulk work out to cheaper workers. Its measured examples cut both ways — an orchestrator set-up cost about half as much on one benchmark and lost on cost on a harder one — so routing is a hypothesis to test on your own evals, not a guaranteed saving.

Which lever first?

What does the traffic look like?
  • Long prefix repeats
    Prompt cachingstable content first
  • Nobody waits for it
    Batch APIplus 1-hour cache
  • Simple task, big model
    Smaller model or effortonly if evals hold
  • User waits, feels slow
    Stream, shorten outputcut time to first token
Diagnose the traffic before choosing. The same system often needs two or three levers, one per workload.
Caching and effort in one requestpython
response = client.messages.create(
    model="claude-sonnet-5",
    max_tokens=1024,                         # a cap, not a length request
    output_config={"effort": "low"},         # routine question
    system=[{
        "type": "text",
        "text": POLICY_AND_EXAMPLES,         # long, identical every call
        "cache_control": {"type": "ephemeral"},
    }],
    messages=[{"role": "user", "content": f"{now()} | {question}"}],
)
u = response.usage
print(u.cache_read_input_tokens, u.input_tokens, u.output_tokens)

Traps the wrong answers are built from

Tempting but wrongDo this instead
Putting timestamps or user details at the top of a cached promptPut stable content first and per-request data after the cache breakpoint.
Using max_tokens to make answers shorterAsk for brevity in the prompt; keep max_tokens as a safety cap that shouldn't normally be hit.
Sending interactive traffic through the Batch API to save 50%Batch only work nobody is waiting for; results can take up to 24 hours.
Switching to a cheaper model based on list priceMeasure cost per successful task on your evals, with each model's own token counts.
Optimising before the prompt worksReach target quality first, then apply levers and re-check quality after each.

You should now be able to

  • Compute per-request and daily cost from the usage fields and the price list, including cache reads and batch discounts.
  • Structure prompts so caching works, and explain its minimum length, lifetime and break-even.
  • Choose between caching, batching, model choice, effort, output length, input trimming and streaming for a given workload.
  • Explain the latency effect of each lever, including time to first token and streaming.
  • Recognise when a saving costs quality, and require eval evidence before accepting it.

Practice questions

Original questions written for this lesson, in the exam’s style. Answer first, then open the reasoning — every option is explained, including why the wrong ones are tempting.

  1. Question 1

    A claims assistant sends the same 9,000-token system prompt with every request, about 30 requests a minute. Cost is over budget and quality is fine.

    Which change is most likely to cut cost without affecting output quality?

    1. AMove to a smaller model for every request.
    2. BSet max_tokens lower to reduce spend.
    3. CCache the system prompt as a stable prefix.
    4. DSend requests through the Batch API.
    Show answer and reasoning
    1. AIncorrect. Could cut cost, but it changes quality and needs eval evidence first; caching doesn't.
    2. BIncorrect. Truncates answers rather than shortening them, and doesn't touch the 9,000 repeated input tokens.
    3. CCorrect. The prefix repeats well within the cache lifetime, so reads bill at a tenth of normal input with identical output.
    4. DIncorrect. The assistant is interactive; batch results can take up to 24 hours.
  2. Question 2

    A team added cache_control to its system prompt, but cache_read_input_tokens is always 0 on Claude Sonnet 5.

    Which two causes could explain this? (Select 2.)

    1. AThe system prompt starts with the current time, so the prefix differs every request.
    2. BThe cached system prompt is 700 tokens long.
    3. CThe responses are longer than 1,000 tokens.
    4. DThe requests use streaming.
    5. EThe team uses the default 5-minute lifetime.
    Show answer and reasoning
    1. ACorrect. Any change before the breakpoint creates a new prefix, so nothing ever matches.
    2. BCorrect. Below the model's minimum cacheable length nothing is cached, and no error is returned.
    3. CIncorrect. Output length has no effect on whether the input prefix is cached.
    4. DIncorrect. Streaming changes how output is delivered, not how the input prefix is cached.
    5. EIncorrect. With steady traffic, 5 minutes is enough; lifetime isn't why every request misses.
  3. Question 3

    Users of an internal research assistant say it “feels frozen” for several seconds before long answers appear. Total generation time is acceptable to them once text starts.

    What is the most appropriate first change?

    1. AMove the workload to the Batch API.
    2. BStream the response so text appears as it's generated.
    3. CLower max_tokens so answers finish sooner.
    4. DSwitch to the most capable model available.
    Show answer and reasoning
    1. AIncorrect. Batch is asynchronous and would make the wait longer, not shorter.
    2. BCorrect. The complaint is time to first visible output; streaming targets exactly that.
    3. CIncorrect. Answers would be cut off mid-sentence; users said total time was fine.
    4. DIncorrect. A larger model doesn't reduce the wait and usually costs more per token.
  4. Question 4

    A team moves a classification job to a model with a lower per-token price, expecting a 40% saving. The bill falls by far less. What is the most likely explanation?

    1. ABatch discounts don't apply to the new model.
    2. BPrompt caching is disabled on newer models.
    3. CThe new model's tokenizer counts the same text as more tokens.
    4. DOutput tokens are free on the old model.
    Show answer and reasoning
    1. AIncorrect. The Batch API discount applies across current models; nothing suggests they used batch.
    2. BIncorrect. Current models support caching; the minimum length differs by model, but caching isn't disabled.
    3. CCorrect. Claude 4.7 and later models produce roughly 30% more tokens for the same text, eroding a per-token saving.
    4. DIncorrect. Output is billed on every model, at five times the input rate in the current price list.

Sources

Drafted with AI assistance and checked against the sources above; expert review is in progress. Spotted an error? Tell us and it gets fixed, dated and listed on how this is written.