Controlling cost and latency

Claude API · Expert · 12 min

Token bills grow quietly with usage; a few design choices often cut them several-fold.

Cost on the Claude API is tokens times price, and price depends on the model. Latency (waiting time) mostly depends on the model and how many output tokens it writes. Most savings come from a few levers, roughly in order of impact:

  • Right-size the model. Route simple steps (classification, extraction) to a small model and keep the large one for hard reasoning. A cheap model screening requests first is a common pattern.
  • Effort and thinking. Lower effort on simple tasks; thinking tokens are output tokens and are billed in full even when you only see a summary.
  • Output length. Output tokens cost several times more than input. Ask for concise formats, use structured outputs instead of prose, and set a sensible max_tokens.
  • Prompt caching. Cache long system prompts, documents and tool lists; reads are a small fraction of normal input price and also ease rate limits.
  • Batches. Anything that can wait up to a day costs about half.
  • Context hygiene. Trim old turns and large tool results in long conversations instead of resending them forever.

Measure before and after: log usage per request (input, output, cache read, cache write) with the model and a feature label, then sum by feature. count_tokens lets you estimate before running a big job. Set a monthly spend limit in the Console so a bug cannot burn the budget.

For latency, stream the answer, keep prompts short, and remember a smaller model or lower effort answers sooner.

Example

import anthropic

client = anthropic.Anthropic()

def route(question: str) -> str:
    # cheap model decides if the question is hard
    r = client.messages.create(
        model="claude-haiku-5-5", max_tokens=5,
        system="Reply only EASY or HARD.",
        messages=[{"role": "user", "content": question}])
    return "claude-opus-5-5" if "HARD" in r.content[0].text else "claude-haiku-5-5"

def answer(question: str):
    model = route(question)
    r = client.messages.create(model=model, max_tokens=400,
                               messages=[{"role": "user", "content": question}])
    u = r.usage
    print(f"{model}: in={u.input_tokens} out={u.output_tokens} "
          f"cache_read={u.cache_read_input_tokens}")
    return r.content[0].text

answer("What is 2 + 2?")

Remember

  • Biggest levers: model routing, output length/effort, caching, batches
  • Log usage per feature so you know where money goes
  • Set a spend limit as a safety net

Watch out for

  • Optimising input tokens while ignoring output and thinking tokens, which cost more.

Check yourself

  1. Which change usually saves most on a chatbot with a 20,000-token system prompt?

Sign in to answer, see the explanations, and get this lesson back as a quick review later.

Official docs: platform.claude.com/docs/en/about-claude/pricing