Jun 21, 2026 · 6 min · API

Choosing the Right Model for the Job (and the Budget)

Choosing the Right Model for the Job (and the Budget)

At 9:17 a.m. on a Tuesday, our support summarizer looked “healthy” on the dashboard: 99.4% success rate, p95 latency under 3 seconds, no queue buildup. The bill told a different story. We were spending Opus-class money to summarize tickets like:

{
  "subject": "Can I reset my password?",
  "messages": 3,
  "language": "en",
  "attachments": 0
}

That is not a reasoning problem. It is not a 1M-context problem. It is barely a language problem.

The fix was not “use the cheapest model everywhere.” That breaks the moment you hit a refund dispute, a tangled bug report, or a compliance-sensitive escalation. The fix was routing: start cheap, measure confidence, escalate only when the task actually earns it.

Choosing the right model is less about finding “the best AI model” and more about building a boring, reliable decision system:

That is where Haiku, Sonnet, Opus, Fable, GPT, Gemini, and open-weight models each have a real place.

The Useful Mental Model: Task Shape First, Model Second

In practice, I classify LLM workloads along five axes before I even look at model names:

Task ShapeExampleBest First PickEscalate When
Simple transformationRewrite, classify, summarize short textHaiku-class or small open modelOutput is malformed or confidence is low
Structured extractionParse invoices, tickets, logsHaiku/Sonnet or constrained open modelAmbiguous fields, high-value record
Product reasoningAgent planning, debugging, multi-step supportSonnet/GPT/Gemini-classTool failures, contradictions, low confidence
Deep analysisArchitecture review, legal-ish policy comparison, complex code reasoningOpus/GPT-5.5/Gemini 3Usually start here if stakes are high
Huge-context synthesisWhole repo, large transcript archive, long docsFable 5 or long-context modelNeed precise local reasoning after retrieval
High-volume private/offlineModeration prefilter, embeddings-adjacent classification, internal batch jobsOpen-weight Llama/Qwen/DeepSeek/MiniMax/KimiEdge cases, regulated decisions

Model choice becomes much easier once you stop asking “which model is smartest?” and start asking “what failure mode am I buying down?”

For example:

The wrong model is often not technically wrong. It is economically wrong.

A Practical Model Ladder

Here is the ladder I use for most production systems.

Haiku-Class Models: The Default for Cheap, Fast Language Work

Haiku-class models are excellent first-pass workers. I use them for jobs where the answer is short, the input is clean, and the output format is constrained.

Good fits:

Example prompt for a cheap first-pass classifier:

{
  "model": "claude-haiku-4.5",
  "temperature": 0,
  "max_tokens": 120,
  "response_format": { "type": "json" },
  "messages": [
    {
      "role": "system",
      "content": "Classify the support ticket. Return only valid JSON."
    },
    {
      "role": "user",
      "content": "Subject: Refund not received\nBody: I canceled two weeks ago and still see a charge."
    }
  ]
}

Expected output:

{
  "category": "billing",
  "urgency": "medium",
  "needs_human": true,
  "reason": "Refund dispute involving payment status"
}

A common gotcha: teams ask cheap models to both reason and format perfectly in one shot. If the model sometimes emits invalid JSON, do not immediately jump to Opus. First tighten the task:

For many production tasks, one retry on Haiku-class is still cheaper and faster than defaulting to a frontier reasoning model.

Sonnet-Class Models: The Workhorse for Real Product Logic

Sonnet-class models are where I usually land for interactive product features. They are strong enough for reasoning, stable enough for tool use, and usually fast enough for user-facing flows.

Good fits:

In practice, Sonnet is often the best “don’t make me think too hard about routing” choice. If you can only integrate one model tier into a new feature, start here.

Example: a support agent that can inspect an order, policy, and prior tickets.

SYSTEM = """
You are a support resolution assistant.
Use tools before making claims about orders, refunds, or account state.
If policy is ambiguous, say what is ambiguous and escalate.
Return:
- summary
- recommended_action
- customer_reply
- escalate: true/false
"""

request = {
    "model": "claude-sonnet-4.6",
    "temperature": 0.2,
    "max_tokens": 900,
    "tools": [
        {"name": "get_order", "description": "Fetch order state"},
        {"name": "get_refund_policy", "description": "Fetch current refund rules"},
        {"name": "search_prior_tickets", "description": "Search customer history"}
    ],
    "messages": [
        {"role": "system", "content": SYSTEM},
        {"role": "user", "content": "Customer says they returned item A but were charged again."}
    ]
}

What actually happens when you run this kind of workflow in production: most failures are not “the model is dumb.” They are integration failures.

A Sonnet-class model gives you enough intelligence to recover from some messiness, but it does not remove the need for clean tool contracts.

Opus-Class Models: Expensive, But Sometimes Cheaper Than Mistakes

Opus-class models are for tasks where the cost of a bad answer dominates the cost of inference.

I reach for Opus when:

Examples:

I do not use Opus for every “important” task. Importance and difficulty are different. A million password reset tickets are important to users, but they are not individually hard. A single subtle data deletion migration may be both important and hard.

A useful pattern is “escalate on uncertainty”:

def choose_model(task):
    if task["context_tokens"] > 700_000:
        return "fable-5"

    if task["risk"] == "high" and task["requires_reasoning"]:
        return "claude-opus-4.8"

    if task["requires_tools"] or task["multi_step"]:
        return "claude-sonnet-4.6"

    return "claude-haiku-4.5"

That is intentionally simple. The router should be boring enough that your team can debug it at 2 a.m.

Fable 5 and 1M Context: Use It When Retrieval Is the Problem

Long context models are tempting because they remove a lot of retrieval engineering. Fable 5’s 1M context window changes what you can attempt directly: whole-document review, giant transcript synthesis, large repository inspection, and multi-file policy analysis.

But long context is not magic.

A 1M-token window helps when the hard part is “the relevant fact might be anywhere.” It does not guarantee the model will reason perfectly across all million tokens, and it does not make irrelevant context free. Long prompts still cost money, add latency, and can dilute attention.

I use Fable-style long context when:

Example architecture for large document review:

User request
  -> lightweight classifier
  -> retrieve obvious relevant sections
  -> if confidence high: Sonnet answer with citations/quotes from chunks
  -> if confidence low or query is global: Fable 5 over full document set
  -> optional Opus review for high-risk final answer

This hybrid works better than “always stuff everything into context.” In practice, long-context models are most valuable as an escape hatch when retrieval confidence is low.

Open-Weight Models: Control, Cost, and Throughput

Open-weight models like Llama, Qwen, DeepSeek, MiniMax, and Kimi are not just “cheaper alternatives.” They are operational choices.

They make sense when you need:

They are especially good for narrow, repeated tasks. For example, a Qwen or Llama variant behind vLLM can handle classification, extraction, and internal enrichment at high throughput if you control prompt length and output format.

Example local serving shape:

vllm serve Qwen/Qwen3-14B \
  --host 0.0.0.0 \
  --port 8000 \
  --tensor-parallel-size 2 \
  --max-model-len 32768 \
  --gpu-memory-utilization 0.90

Then call it through an OpenAI-compatible client:

from openai import OpenAI

client = OpenAI(
    base_url="http://localhost:8000/v1",
    api_key="local"
)

result = client.chat.completions.create(
    model="Qwen/Qwen3-14B",
    temperature=0,
    messages=[
        {"role": "system", "content": "Return valid JSON only."},
        {"role": "user", "content": "Classify: user cannot access invoice PDF"}
    ]
)

The trade-off is engineering ownership. With hosted frontier models, someone else handles capacity, patching, quantization choices, and kernel-level performance work. With open models, that becomes your job.

Open-weight models are a great fit when the workload is stable. They are a worse fit when the product is changing weekly and prompt quality matters more than raw serving cost.

Cheap-First Routing With Escalation

A good router is not a leaderboard. It is a risk control system.

Here is a production-friendly pattern:

  1. Try the cheapest model that should be capable.
  2. Validate the output mechanically.
  3. Ask the model for a calibrated self-check only on observable criteria.
  4. Escalate if validation fails, confidence is low, or risk is high.
  5. Log the route and outcome for later tuning.

Example router:

def run_with_escalation(task, input_text):
    first_model = pick_first_model(task)

    response = call_model(
        model=first_model,
        input=input_text,
        schema=task["schema"],
        temperature=0
    )

    validation = validate(response, task["schema"])

    if not validation.ok:
        return call_model(
            model="claude-sonnet-4.6",
            input=input_text,
            schema=task["schema"],
            temperature=0
        )

    if task["risk"] == "high" and response.get("needs_review"):
        return call_model(
            model="claude-opus-4.8",
            input=input_text,
            schema=task["schema"],
            temperature=0
        )

    return response

The important part is that escalation is based on measurable signals, not vibes.

Useful escalation signals:

Avoid using only “model confidence” as a numeric score. LLM confidence is not a calibrated probability. It is still useful when constrained to specific checks: “Did the input contain enough information to answer?” is better than “How confident are you?”

Latency, Price, and User Experience

The fastest model is not always the best UX. The best UX is the one that gets the user to a correct result with tolerable waiting.

For interactive systems, I think in latency budgets:

ExperienceRough BudgetModel Strategy
Autocomplete or inline assist100–500 ms perceivedSmall/open model, streaming, aggressive caching
Chat response1–5 secondsHaiku/Sonnet-class with streaming
Agentic tool workflow5–20 secondsSonnet-class, parallel tools, progress updates
Deep analysis30–180 secondsOpus/Fable/GPT/Gemini-class, async job
Batch processingMinutes to hoursOpen-weight or cheapest hosted tier

Do not hide slow reasoning behind a spinner without feedback. If an Opus or Fable job needs 90 seconds, make it an explicit analysis task:

Analyzing 184 files...
✓ Indexed repository structure
✓ Found 12 migration scripts
✓ Checking rollback safety

That changes user perception because the system is doing visible work.

Also, stream whenever possible. Streaming does not reduce total completion time, but it improves perceived latency dramatically for chat and drafting workflows.

Real Per-Task Decisions

Here are concrete choices I would make today.

Support Ticket Triage

Use Haiku first.

This is a classic cheap-first workflow.

Customer-Facing Support Agent

Use Sonnet.

Use Haiku only for preprocessing. Use Opus for supervisor review on high-risk cases.

Code Review Assistant

Use Sonnet for ordinary PR review. Use Opus for architecture-sensitive changes, concurrency, security, data migrations, and subtle correctness work.

A common mistake is feeding the whole repo by default. Start with the diff, dependency graph, and nearby files. Escalate to Fable or another long-context model only when the change spans many areas.

Long Contract or Policy Comparison

Use retrieval plus Sonnet for narrow questions. Use Fable 5 when the question is global, like “find all contradictions across these documents.”

If the output influences a real legal or compliance decision, use the model to prepare analysis, not to make the decision.

High-Volume Data Enrichment

Use an open-weight model if volume is high and the task is stable.

Example:

Run nightly batches, validate samples, and escalate edge cases to a hosted model.

Research Assistant Over Large Archives

Use Gemini 3, GPT-5.5, Opus, or Fable depending on context length and reasoning needs. I would not cheap-first this unless the query is obviously simple. Research failures are often silent: the model gives a plausible answer while missing the key document.

Budgeting Without Lying to Yourself

The easiest way to overspend is to optimize per-call cost while ignoring retries, human correction, and failed workflows.

Track these metrics by task type and model:

That last one matters. A cheap model that requires three retries and still causes manual review may be more expensive than Sonnet. An Opus call that prevents a bad migration can be the cheapest decision of the week.

If you use a multi-model gateway, including something like AI Prime Tech’s API access across Claude, GPT, and Gemini families, the main benefit is not just vendor optionality. It is making routing and measurement easier across model classes. But the hard part is still your task design.

Practical Takeaways

RW
Ryan Walsh · Developer Tools & Claude Code

Ryan lives in the terminal with Claude Code and follows the Anthropic developer ecosystem closely — MCP servers, subagents, hooks, skills, and the coding-agent workflows developers actually ship with.

Get cheaper Claude API access

One API key for Claude Opus 4.8, Sonnet 4.6, Haiku 4.5, Fable 5, plus GPT & Gemini — up to 80% off official pricing, pay-as-you-go.

Get Your API Key →
AI Prime Tech is an independent third-party API gateway. Claude™ and Anthropic® are trademarks of Anthropic, PBC. No affiliation or endorsement is implied.