Claude Opus Thinking Cost Runaway — Fix (2026) | AI Error Hub
Anthropic Claude Model-Specific Severity: Critical Cost issue

Claude Opus + Extended Thinking — Cost Runaway

Opus 4.6 outputs at $75/M tokens. Extended thinking counts as output. A 32K thinking budget = $2.40 per request just for thinking. Bills explode when Opus + high thinking budget is used at scale. Fix: right-size the budget, use Sonnet for most work, cache aggressively, alert on cost anomalies.

Error surface: Cost management Category: Model-Specific Rate: $75/M output tokens (Opus 4.6) Last tested: Nov 15, 2026
Quick Fix (TL;DR)

Rule of thumb: Sonnet 4.5 with 10K thinking = $0.15/request. Opus 4.6 with 32K thinking = $2.40/request (16× more). Reserve Opus for genuinely hard problems (proofs, high-stakes analysis). Cap Opus thinking budget at 16K unless justified. Alert when any request exceeds $1. Cache aggressively to reduce input side.

The Cost Math

ConfigThinking costNotes
Opus 4.6, 32K budgetUp to $2.4032,000 × $75/M
Opus 4.6, 16K budgetUp to $1.2016,000 × $75/M
Opus 4.6, 8K budgetUp to $0.608,000 × $75/M
Sonnet 4.5, 32K budgetUp to $0.4832,000 × $15/M
Sonnet 4.5, 10K budgetUp to $0.1510,000 × $15/M
Haiku 4.5, 5K budgetUp to $0.0255,000 × $5/M

These are worst cases (full budget used). Actual usage is often 40-70% of budget. But at scale, worst-case × 10K requests/day = real money.

The Symptoms You're Seeing

Runaway cost signals
Monthly bill: $500 → $18,000 after enabling Opus thinking
  → 36× jump; unmanaged budget expansion

Per-request usage.output_tokens shows 8,000-30,000 regularly
  → Thinking dominating output tokens

Cost per user query: $0.02 (Sonnet) → $2.40 (Opus 32K thinking)
  → Direct 100× multiplier

Alerts firing on account balance
  → Reactive; too late

Team debating: "does the answer quality justify 100× cost?"
  → The right conversation, but usually starts too late

Rate limit hits despite low RPM
  → TPM (tokens per minute) limits hit before RPM

What Actually Causes Runaway

40%
Default max thinking budget applied everywhereTeam set 32K globally; used on every request regardless of task.
25%
Opus chosen when Sonnet suffices"Better model = better answer"; ignored 5× cost multiplier.
15%
No prompt cachingInput side also runs high on Opus ($15/M); cache saves 90%.
10%
Agent loops with thinkingMulti-turn agent, each turn thinks 8K; 10 turns = 80K thinking tokens.
7%
No per-request cost loggingCan't identify expensive requests until bill hits.
3%
Bug: thinking enabled on non-reasoning tasksFeature flag flipped everything; nobody caught it.

Fixes That Work (Tested Nov 2026)

1Task-Sized Budget + Model Selection

Python · routing by task complexity
TASK_CONFIGS = { # Simple lookup — no thinking needed "simple_qa": { "model": "claude-haiku-4-5", "thinking": None, "max_tokens": 2048 }, # Regular reasoning — Sonnet default "standard_analysis": { "model": "claude-sonnet-4-5", "thinking": {"type": "enabled", "budget_tokens": 4000}, "max_tokens": 8192 }, # Complex multi-step — Sonnet + more thinking "complex_workflow": { "model": "claude-sonnet-4-5", "thinking": {"type": "enabled", "budget_tokens": 10000}, "max_tokens": 16000 }, # Hard reasoning — Opus, capped budget "deep_reasoning": { "model": "claude-opus-4-6", "thinking": {"type": "enabled", "budget_tokens": 10000}, "max_tokens": 16000 }, # Only for truly hard, high-stakes cases "critical_analysis": { "model": "claude-opus-4-6", "thinking": {"type": "enabled", "budget_tokens": 20000}, "max_tokens": 32000, "cost_alert": True # flag for observation } } def make_request(task_type, messages): cfg = TASK_CONFIGS[task_type] return client.messages.create(messages=messages, **{ k: v for k, v in cfg.items() if not k.startswith("cost_") })

2Cost Estimation Before Request

Python · budget guard rail
RATES = { # $ per million tokens "claude-opus-4-6": {"input": 15, "output": 75}, "claude-sonnet-4-5": {"input": 3, "output": 15}, "claude-haiku-4-5": {"input": 1, "output": 5}, } def estimate_max_cost(model, input_tokens, max_output_tokens, thinking_budget=0): """Worst-case cost estimate before sending.""" rates = RATES[model] input_cost = input_tokens * rates["input"] / 1_000_000 # Both output tokens AND thinking count at output rate output_cost = (max_output_tokens + thinking_budget) * rates["output"] / 1_000_000 return input_cost + output_cost def safe_create(cost_ceiling_usd=1.00, **kwargs): input_tokens = client.messages.count_tokens(**kwargs).input_tokens thinking = kwargs.get("thinking", {}) or {} thinking_budget = thinking.get("budget_tokens", 0) max_cost = estimate_max_cost( kwargs["model"], input_tokens, kwargs.get("max_tokens", 4096), thinking_budget ) if max_cost > cost_ceiling_usd: raise ValueError( f"Request max cost ${max_cost:.2f} exceeds ceiling ${cost_ceiling_usd}" ) return client.messages.create(**kwargs)

3Aggressive Caching + Cost Observability

Python · cache and observe
def log_actual_cost(response, model): rates = RATES[model] u = response.usage # Cached input at 10% of rate input_cost = ( u.input_tokens * rates["input"] + u.cache_read_input_tokens * rates["input"] * 0.1 + u.cache_creation_input_tokens * rates["input"] * 1.25 ) / 1_000_000 output_cost = u.output_tokens * rates["output"] / 1_000_000 total = input_cost + output_cost metrics.emit("claude.cost.request", total, tags={"model": model}) if total > 1.00: logger.warning( f"Expensive request: ${total:.2f} " f"(model={model}, output_tokens={u.output_tokens})" ) return total # Cache Opus prompts aggressively — save 90% on repeated input response = client.messages.create( model="claude-opus-4-6", system=[{"type": "text", "text": LARGE_SYSTEM, "cache_control": {"type": "ephemeral", "ttl": "1h"}}], extra_headers={"anthropic-beta": "extended-cache-ttl-2025-04-11"}, thinking={"type": "enabled", "budget_tokens": 10000}, max_tokens=16000, messages=messages ) log_actual_cost(response, "claude-opus-4-6")
Do the math before deploying

Estimate cost of ONE request, then multiply by projected daily volume. Sonnet at 10K daily requests with 5K thinking = ~$1,000/day. Opus same setup = ~$5,000/day. Whether it's worth 5× depends on downstream value. Make this decision with data, not vibes.

Preventing This Error Going Forward

  • Default to Sonnet, escalate to Opus explicitly. Not the other way around.
  • Cap thinking budget by task category. 32K only for justified cases.
  • Estimate max cost before every request. Fail loud if over ceiling.
  • Log actual cost per request. Alert on outliers immediately.
  • Cache aggressively. Cuts input side by 90% at high scale.
  • Set org-level spend limits in console. Hard cap as last resort.
  • Run cost postmortem weekly. Which endpoints drive spend?
SK
Tested by Sana K.
Researcher · AI Error Hub
Last verified: Nov 15, 2026 · SDK: anthropic 0.42

Frequently Asked Questions

Genuinely hard reasoning: novel proofs, cutting-edge research assistance, high-stakes financial analysis, medical decision support (with human review). If a downstream decision hinges on getting the reasoning right and the cost of wrong is > $10, Opus pays off. For content generation, chatbots, summaries: Sonnet is almost always the correct choice.

Yes — thinking and redacted_thinking blocks appear in response.content. Their token count is included in usage.output_tokens. You can inspect what Claude thought about (useful for auditing whether thinking budget is well-spent).

No — caching only affects INPUT tokens. Thinking is generated fresh each request (that's the point). Caching still helps because Opus input is $15/M; 100K cached tokens = $1.35 saved vs uncached per request.

No streaming interrupt for thinking. Set the budget at request time; Claude respects it as a cap. If Claude would exceed budget, it wraps up early. So over-shooting the budget cap is impossible — but Claude might use the full amount even for simple queries if budget is very high.

Often yes. Baseline Sonnet without thinking is $3/M input, $15/M output — plenty capable for chat, extraction, summarization, most analysis. Enable thinking selectively for reasoning-heavy queries. A/B test with/without; measure quality delta vs cost.