Domain V5 of the Claude Certified Developer – Foundations (CCDV-F) exam is titled Model Selection and Optimization, and it carries roughly 16.8% of the total exam weight — the largest single domain on the test. Anthropic breaks it into four sub-objectives: LLM Fundamentals (5.2%), Technical Fundamentals — the SDKs you use wrap a REST and streaming transport underneath (6.1%), Model Selection and Tradeoffs — when to reach for Opus, Sonnet, Haiku, or Fable, and what adaptive thinking changes about the answer (2.7%), and Cost and Token Management — tracking spend, modeling cost, and using prompt caching correctly (2.8%).
This guide is an independent, unofficial study resource. It is not affiliated with, authorized by, or endorsed by Anthropic, and it reproduces no real exam items. Model IDs, pricing, and API behavior described here reflect the Claude API as documented on platform.claude.com at the time of writing — verify current specifics there, since model tiers and pricing change on a schedule the exam expects you to be aware of, not oblivious to.
Treat every question in this domain as a production decision, not a trivia lookup. The exam rewards developers who can justify a model choice against latency, cost, and capability requirements — and who know which parts of the API surface are model-dependent rather than universal. That second point is the domain's favorite trap: an API shape that works on one model tier can silently fail on another.
Tokens, context windows, and what a model actually sees
Everything Claude reads and writes is measured in tokens, not characters or words. A token is roughly three to four characters of English text on average, though the ratio varies with language, code, and formatting — Claude never sees your prompt as a string, it sees a sequence of token IDs, and every billing figure, every context-window limit, and every output-length setting is denominated in that unit, not in bytes or words.
The context window is the combined budget for everything a single request touches: your system prompt, the full conversation history you resend, any tool definitions, and the space reserved for the response. It is not a per-turn allowance — in a multi-turn conversation, each new request typically resends the entire prior transcript, so the context window is a hard ceiling on how much history plus output a single call can carry, and it fills up in practice as a conversation grows even though the model's rated context-window number never changes.
Adaptive thinking is the mechanism that replaced the older fixed thinking-token-budget approach on the newest models. Instead of you specifying a hard token ceiling for the model's internal reasoning before it starts, the model decides for itself when a task warrants deeper reasoning and how much of it to do — you influence the depth through an effort setting rather than a token count. This has a direct latency and cost consequence: turning reasoning on, or raising effort, doesn't just change answer quality, it adds tokens you're billed for and time you wait for, on top of the visible response. A request that used to have a predictable token ceiling now has a more variable one, shaped by how hard the model judges the task to be.
- Higher effort settings generally mean more reasoning tokens, higher cost, and higher latency — not a free quality upgrade.
- Reasoning tokens are billed as part of output, even when the model's internal reasoning is never shown to the user.
- A task that doesn't need deep reasoning still pays some tax if effort is set too high for it — matching effort to task difficulty is itself a cost lever, not just a quality one.
SDKs are a convenience layer, not a different API
It's easy to think of the SDK you import as its own thing with its own rules. Underneath, every SDK call is a thin wrapper around two transports: a standard request/response call for a complete answer, and a streaming transport that delivers the response incrementally as it's generated, for cases where you want to start displaying output before the model finishes. The SDK's job is ergonomics — typed request and response objects, automatic retries on transient failures, and helpers that assemble a streamed response into a single object for you — not new capability the underlying transport doesn't already expose.
This matters for the exam because it means nothing about pricing, context windows, rate limits, or model behavior lives "in the SDK." Those are properties of the account, the model, and the request itself. Swapping SDK language, or dropping to raw HTTP calls entirely, changes nothing about what you're billed or what the model can do — it only changes how much boilerplate you write to get there.
Two operational consequences follow directly from treating the SDK as a wrapper. First, error handling belongs at the transport layer: a rate-limit response, an authentication failure, or a malformed request comes back as a standard error your SDK surfaces in its own idiom, but the underlying cause and remedy are the same regardless of which SDK raised it. Second, because the SDK is not where model selection or cost logic lives, none of that logic should be hidden inside SDK configuration either — the model ID, the token budget, and the caching strategy are request-level decisions your application code should own and be able to reason about explicitly, not defaults buried in a client constructor.
Choosing a model: Opus, Sonnet, Haiku, or Fable
The current lineup spans four tiers, and the exam expects you to reason about the tradeoff between capability, latency, and cost rather than defaulting to the most powerful option out of habit.
| Model | Price (input / output per MTok) | Context window | Best-fit use case |
|---|---|---|---|
| Claude Fable 5 | $10 / $50 | 1M tokens | Highest-capability tier — reach for it only when a task genuinely needs the ceiling |
| Claude Opus 5 | $5 / $25 | 1M tokens (128K max output) | Anthropic's recommended default for complex agentic coding and enterprise work |
| Claude Sonnet 5 | $2 / $10 | 1M tokens (128K max output) | Best combination of speed and intelligence — the workhorse tier for most production traffic |
| Claude Haiku 4.5 | $1 / $5 | 200K tokens (64K max output) | Latency-critical or simple, high-volume tasks |
Notice that Sonnet 5's pricing is itself a real exam-relevant detail: at $2 input / $10 output per million tokens, it is cheaper than the prior generation Sonnet 4.6 was at $3/$15 — a reminder that a model tier's relative cost position isn't fixed across generations. A workload sized against last generation's pricing table needs to be re-sized, not assumed to still hold.
Fold adaptive thinking back into this decision: a harder task run on a cheaper model at high effort can end up costing more, in both tokens and latency, than the same task on a stronger model at lower effort — because effort spend and model capability are two separate levers on the same problem. Model selection and thinking configuration are not independent choices; they're two variables you tune together against the same latency and cost budget.
The thinking and sampling APIs are model-dependent — don't assume portability
This is the domain's sharpest trap, and it's worth stating plainly: the request shape that configures extended reasoning is not the same across every current model, and code written against one model's shape can fail outright on another.
| Model | Extended-thinking mechanism |
|---|---|
| Claude Fable 5 / Opus 5 / Sonnet 5 | The older fixed-budget mode is removed. Reasoning is configured with an adaptive thinking setting plus an effort parameter — the model decides how much to think, and effort tunes the depth. |
| Claude Haiku 4.5 | The only current-tier model that still supports the older "classic" extended-thinking mode, with an explicit budget_tokens parameter that sets a hard reasoning-token ceiling up front. |
A related, narrower trap sits on the newest model tier specifically: temperature, top_p, and top_k are general Messages API parameters that exist and work on many models, but they are rejected outright — a 400 error — on the newest model tier. Developers who default to setting temperature on every request, out of habit from earlier model generations, will find that habit breaks the moment the same request is pointed at the newest tier. These are per-model restrictions to account for in a multi-model codebase, not universal parameters you can set once and forget.
- Never assume a request payload that works on one model tier is valid on another without checking that tier's supported parameters first.
- A codebase that routes across model tiers needs its request-building logic branched or abstracted by model capability, not written once against a single tier's shape.
- Treat "is this parameter still supported on the model I'm calling" as a standing question whenever you add a new model to an existing routing layer.
Token tracking and cost modeling
Anthropic exposes a dedicated endpoint for counting tokens before you spend money on a request: it accepts the same input shape as a normal Messages API call and returns just the input token count, and — unlike the inference call itself — it's free to use, though it's rate-limited separately from your inference traffic. Calling it before a request lets you estimate cost, check you're inside the context window, or decide whether to route to a cheaper model, all without paying for a completion.
Cost modeling for a real workload comes down to multiplying a per-request token estimate by request volume and by the model's per-token price — separately for input and output, since they're priced differently on every tier. The worked example below walks through exactly that arithmetic, once without any optimization and once with prompt caching applied to the stable portion of the prompt, so you can see where the savings actually come from and where they don't.
Worked example: suppose an application sends 10,000 requests per day, each with 2,000 input tokens — 1,500 of which are a stable system prompt plus shared context that doesn't change per request, and 500 of which are the unique per-request question — and 500 output tokens, running on Claude Sonnet 5 at $2 input / $10 output per million tokens.
| Scenario | Input cost / day | Output cost / day | Total / day |
|---|---|---|---|
| No caching — full 2,000 input tokens billed on every request | 20M tokens × $2/MTok = $40.00 | 5M tokens × $10/MTok = $50.00 | $90.00 |
| With prompt caching on the 1,500-token stable prefix (cache stays warm; ~1 write, 9,999 reads) | ≈ $3.00 cache reads + $10.00 uncached remainder + negligible write ≈ $13.00 | 5M tokens × $10/MTok = $50.00 (unchanged) | ≈ $63.00 |
Two things stand out. First, caching cut this workload's total daily cost by roughly 30% — but every dollar of that saving came from the input side; the $50-per-day output cost didn't move at all, because caching only discounts input tokens the model reads, never the tokens it generates. Second, the saving is conditional on the cache actually staying warm: if requests arrived more than five minutes apart on average, the default cache TTL would expire between requests, each one would repay the write premium, and much of this saving would evaporate. Caching is a lever you have to verify is working, not one you can assume is working from the mere presence of a cache marker — the next section covers exactly how to check.
Prompt caching: the mechanics, and what it doesn't fix
Prompt caching lets you avoid re-billing full price for content that repeats identically across requests — a system prompt, a set of tool definitions, a large shared document — by writing it to a cache once and reading from that cache on subsequent requests at a steep discount.
- Cacheable: tools, system blocks, and message content — text, image, document, tool-use, and tool-result blocks.
- Not directly cacheable: thinking blocks (they're only cached as part of a prior assistant turn, not on their own), citations sub-content, and empty text blocks.
The order the request is rendered in matters: tools first, then system, then messages — and the cache breakpoint you mark applies to the last stable block before it, with a 20-block lookback for finding a matching prior cache entry. Content placed after your breakpoint is never cached, so volatile, per-request content belongs at the end of the request, after everything reusable.
| TTL option | Write cost | Read cost |
|---|---|---|
| 5-minute (default) | 1.25x normal input write price | 0.1x base input price |
| 1-hour | 2x normal input write price | 0.1x base input price |
Because a caching failure is silent rather than a hard error, the only reliable way to confirm caching is actually happening is to check the response's usage figures: cache_creation_input_tokens (tokens written to the cache this request) and cache_read_input_tokens (tokens served from the cache at the discounted rate). If both are zero across repeated, identical-prefix requests, the cache isn't engaging — check prefix length against the model's minimum, and check that nothing upstream of your breakpoint is varying between requests.
Key takeaways
- 01Tokens, not characters or words, are the unit everything is billed and bounded in — context window size is a fixed model property, not a request parameter you can raise.
- 02Adaptive thinking replaced fixed thinking-token budgets on Fable 5, Opus 5, and Sonnet 5; effort controls reasoning depth, and higher effort means more billed tokens and more latency, not just better answers.
- 03SDKs are a convenience wrapper over the same request/response and streaming transport — pricing, context limits, and model behavior live at the API and model level, not inside SDK configuration.
- 04Match the model tier to the workload: Opus 5 as the default for complex or high-stakes work, Fable 5 only when the task needs the top capability ceiling, Sonnet 5 for the speed/cost balance, Haiku 4.5 for latency-critical or simple high-volume traffic.
- 05The thinking and sampling APIs are model-dependent — Haiku 4.5 alone still uses classic budget_tokens, and temperature/top_p/top_k are rejected outright on the newest model tier. Code that routes across tiers must branch on model capability.
- 06Recount tokens per target model rather than reusing an old estimate — the newer tokenizer on Claude 4.7+, Fable 5, and Mythos 5 produces roughly 30% more tokens for identical text than older models.
- 07Prompt caching discounts input tokens only — it never reduces output cost — and only pays off when you verify cache_creation_input_tokens and cache_read_input_tokens show it's actually engaging.
Common mistakes
Reusing the same thinking configuration object across every model tier in a multi-model codebase.
Branch request construction by model: Fable 5, Opus 5, and Sonnet 5 need the adaptive thinking plus effort shape; Haiku 4.5 still needs the classic budget_tokens shape. Treat this as a per-model lookup, not a shared default.
Assuming a dateless model ID like claude-opus-5 automatically tracks the newest release of that tier.
Treat every model ID as a pinned snapshot. Plan for a deliberate migration step when a new snapshot ships, rather than assuming behavior or pricing will silently update under your existing code.
Adding a cache marker to a prompt and assuming caching is now saving money, without checking whether it actually engaged.
Check cache_creation_input_tokens and cache_read_input_tokens on the response. A prefix below the model's minimum length, or a prefix that varies between requests, will silently produce zero cache reads with no error.
Treating prompt caching as a general cost-reduction tool that covers the whole request.
Caching only discounts input tokens the model reads — output generation is unaffected in cost and latency. For output-heavy or bulk workloads, pair caching with model-tier selection or batching rather than expecting it to solve cost on its own.
Frequently asked
Does a bigger context window mean a model is always the better choice for a document-heavy task?
Not automatically. Context window is one input to the decision, but cost and latency scale with however many tokens you actually send, regardless of the ceiling. A 1M-token context window on Opus 5 or Sonnet 5 means you can fit a large document, not that doing so is free or fast — check whether a smaller model with a smaller window genuinely can't fit the task before assuming the larger window is required.
If Sonnet 5 is now cheaper than the model it replaced, does pricing only ever go down generation to generation?
No — treat pricing as something to re-check per generation rather than assume a direction for. Sonnet 5's $2/$10 per MTok being cheaper than Sonnet 4.6's $3/$15 is a fact about this specific transition, not a rule. A cost model built against one generation's pricing table needs to be re-verified, not assumed to still hold, whenever a new model snapshot enters your routing logic.
Is streaming a response cheaper than waiting for the full response?
No. Token accounting is identical either way — streaming changes when you receive the tokens, not how many you're billed for. Streaming is a latency and UX decision for interactive applications, not a cost optimization.
Why would setting temperature work in testing and then fail in production?
Almost certainly a model-tier mismatch. temperature, top_p, and top_k are accepted on many models but rejected with a 400 error on the newest model tier. If your testing ran against one tier and production routes some traffic to another, the same request payload can succeed on one and fail on the other.
Independent, unofficial study material. Not affiliated with, endorsed by, or authorized by Anthropic. Every example is original and written to teach the public exam objectives — no real exam questions are reproduced. Technical details reflect Claude, the Anthropic API, Claude Code, and MCP as of August 24, 2026; always confirm specifics against current official documentation.
Test yourself
Turn what you just read into answers you can check.