InterviewKata
AI engineering · Module 19 of 21 · Level 5: Production

Cost, latency and observability

An AI feature that works in a demo can still fail in production: too slow, too expensive at scale, or quietly looping on some inputs. You can't fix what you can't see, so the first step is recording every model and tool call. Then the savings are usually easy to find.

1. The idea

A delivery company doesn't cut costs by guessing. Every van has a tracker: route, stops, fuel, time. The data shows that a few long detours cost the most, that small parcels don't need the big van, and that several drops on one street can happen at once. Trace first, then trim.

Three things to get right:

  1. Observe. Record a trace for every request: each model call and tool call, with the model, tokens, cost, time, errors and (where allowed) the content. OpenTelemetry has standard GenAI fields for this, so any tracing tool can read it.
  2. Cut cost with the levers from Module 04, applied automatically: route easy requests to a smaller model, cache the stable start of prompts, batch anything that can wait, and ask for shorter outputs.
  3. Cut latency where users feel it: stream the answer so the first words appear quickly, run independent tool calls in parallel, use a faster model or less reasoning effort for simple steps.

And set budgets (turn caps, token limits, per-user and per-feature spend limits) so one bad input can't burn a month's budget overnight.

2. How it works

Your app emits spans for each model and tool call. A collector sends them to whichever tracing tool you use. Dashboards, alerts and evals all read from the same traces.

One model-call span, with the standard OpenTelemetry GenAI attribute names (simplified):

{
  "name": "chat claude-sonnet-5-5",
  "duration_ms": 2410,
  "attributes": {
    "gen_ai.request.model": "claude-sonnet-5-5",
    "gen_ai.usage.input_tokens": 3120,
    "gen_ai.usage.output_tokens": 412,
    "gen_ai.response.finish_reasons": ["end_turn"],
    "app.feature": "support-answer",
    "app.cost_usd": 0.0104
  }
}

The gen_ai.* names come from the OpenTelemetry GenAI semantic conventions, which are still evolving. The app.* fields are your own: tag every span with the feature and customer so you can slice cost by them.

3. Try it yourself

Trim the bill

A support feature handles 20,000 requests a day on Claude Sonnet 5.5: 3,000 input tokens and 400 output tokens each. Switch on the levers and watch the monthly cost.

Make it feel fast

One agent request: a planning call, two tool calls, then the answer. Change how it runs and watch the total time and the time until the user sees the first words.

4. Why it matters at work

LeverWhat it savesHow
Model routingCost, latencyA cheap model handles most requests; hard ones (or ones it's unsure about) go to a stronger model. Prove it with evals (Module 17)
Prompt cachingCost, latencyKeep instructions, tool definitions and documents identical and first. Cached input costs 2.5–10% of the normal price (Module 04)
Batch APIHalf the costFor anything that can wait hours: nightly reports, backfills, evals
Shorter outputsCost, latencyOutput tokens cost several times more than input and are generated one by one. Ask for JSON or a fixed length; set max_tokens
Lower reasoning effortCost, latencyOnly spend thinking tokens on steps that need them
StreamingFelt latencyUsers see words after the time to first token, not after the whole answer
Parallel tool callsLatencyIndependent lookups run at the same time
BudgetsRunaway spendTurn caps (Module 16), per-user and per-feature limits, alerts at 50/80/100%

Measure what matters: cost per successful task (not per request), p95 latency and time to first token (not just averages), error and retry rates, and turns per agent run. Track cost per feature and per customer, so a price change is a decision, not a surprise.

Privacy in tracesTraces can contain prompts and outputs, which may include personal data. Decide what you log, redact where needed, set a retention period, and restrict who can read them.

5. In your five tools

Coding tools need the same discipline: know what a session and a month cost you. Checked against vendor documentation, October 2026.

ToolSee cost and usageExport and control
Claude Code/cost: the current session's cost and tokensOpenTelemetry export with CLAUDE_CODE_ENABLE_TELEMETRY=1: metrics such as claude_code.cost.usage and claude_code.token.usage, plus events for API calls and tool decisions
Antigravity CLI/usage (alias /quota): model quota used; /credits: remaining creditsSettings decide whether paid credits are used once plan quotas run out
GitHub CopilotUsage-based billing with GitHub AI Credits since 1 June 2026; your usage page shows credits usedBudgets and spending limits; for organisations, the Copilot usage metrics dashboard and REST API
CursorDashboard: usage and the Spending tabSpend limits (soft or hard, with alerts); for teams, the Admin API returns usage events with tokens and cost
Codex CLI/status in a sessionOpenTelemetry export: an [otel] section in your user-level ~/.codex/config.toml (project config ignores it); prompts are redacted unless you opt in

6. Remember it

Memory hook: "Trace it, price it, trim it"Record every call. Put a price on every feature and customer. Then pull the levers that the data points to.
How this hook works: what “Trace it, price it, trim it” means

What the slogan means, phrase by phrase

“Trace it”
A span for every model and tool call (model, tokens, time, errors), tagged with feature and customer. OpenTelemetry makes it portable.
“price it”
Turn tokens into money per feature, per customer and per successful task, and latency into p95 and time to first token. Now you know where the money and the waiting go.
“trim it”
Route, cache, batch, shorten, stream, parallelise, cap. Check each change with your evals so quality doesn't drop.

Why this picture fits: it stops you optimising blind. The expensive part is rarely where you'd guess: often a few runaway agent runs, or one feature with an uncached 20,000-token prompt.

The story → the concept

The delivery companyYour AI feature
A tracker in every vanA trace for every request
Fuel per routeCost per feature and per customer
Small parcels in a small vanModel routing
Loading the van the same way every morningPrompt caching
Overnight freightBatch API
Several drops on one street at onceParallel tool calls
"Your parcel is on its way" messageStreaming
A fuel card limitBudgets and turn caps

Watch it on an example

  1. Trace: costs jumped 40% this week.
  2. Price: one customer's agent runs average 38 turns instead of 6; their documents make the search tool return nothing useful.
  3. Trim: a turn cap of 12, a better "not found" message from the tool, and an alert at 3× normal cost per customer.

The trap it saves you from

Switching everything to the cheapest model to save money, then losing users because quality dropped and no eval caught it.

It still works when…

You manage your own use of coding agents: check /cost or your usage page weekly, notice which tasks burn tokens, and adjust models, effort and context.

7. Common mistakes

No spend limitsOne looping agent or abusive user can run up a large bill in hours. Cap turns, tokens and spend per user and per feature, with alerts.
Breaking the cache by accidentA timestamp or user name at the top of the system prompt makes every request a cache miss. Put stable content first, changing content last.
Averages onlyAn average of 2 seconds can hide a p95 of 15. Watch percentiles and time to first token.
Cost per request instead of per successA cheaper model that needs three retries, or fails more often, can cost more per finished task.
Logging everything foreverPrompts and outputs may contain personal data. Redact, limit access and set retention.

8. Hands-on lab (roadmap week 24)

  1. Trace your feature from Modules 14–16: one span per model and tool call with model, tokens, duration and a feature tag. Send it to any OpenTelemetry-compatible tool, or start with a log file.
  2. Price it: compute cost per request and per successful task from the token counts and current prices.
  3. Add caching: reorder the prompt so the stable part comes first, and confirm cache reads in the API's usage numbers.
  4. Try routing: run your eval set on a smaller model. For which cases is it good enough? Estimate the saving.
  5. Estimate cost per 1,000 users, and set a budget and alert. Turn on telemetry or check usage in your own coding tool for a week.

9. Self-check quiz

Costs jumped and nobody knows why. What should already have been in place?

With traces tagged by feature and customer, you can find the cause in minutes.

Your cache hit rate is zero. The most likely cause?

Caching matches the start of the prompt exactly. Anything that changes must go after the stable part.

Answers take 8 seconds and users say it "feels broken". The quickest win for felt latency?

Users see the first words after the time to first token, often under a second.

Before routing easy requests to a cheaper model, what must you check?

Savings only count if quality holds on your own cases (Module 17).

10. Go deeper

ResourceTimeWhy
Inside the LLM call: GenAI observability with OpenTelemetry20 minHow the standard GenAI spans and attributes work.
Prompt caching (Claude docs)20 minHow cache breakpoints, lifetimes and pricing work.
Batch APIs: Claude, OpenAI, Gemini30 minHalf-price processing for work that can wait.
Monitoring usage (Claude Code docs)15 minOpenTelemetry metrics and events from a coding agent.