Costs and buying

Token Costs: The Arithmetic Nobody Shows You

Token cost is four multiplications and one division, and most estimates get the division wrong. The six meters a language model system runs, why caching fails silently, and where retrieval money goes.

On this page
  1. The arithmetic, in one place
  2. Tokens are not words, and your spreadsheet knows it
  3. The six meters every language model system runs
  4. Output tokens are the ones that hurt
  5. Prompt caching rewrites the order of your prompt
  6. Retrieval is where the money actually goes
  7. The meters nobody bills for until the invoice arrives
  8. Put a cost line on every request
  9. Terms to be precise about
  10. Before you quote a number to anyone

The arithmetic, in one place

The short answer

Token cost is four multiplications and one division. Multiply fresh input tokens by the input rate, cached input tokens by the cached rate, output tokens by the output rate, add the tokens spent on retries, guardrails and offline evaluation runs, then divide by the fraction of outputs you actually accept. Two mistakes account for most wrong estimates: counting words instead of tokens, and pricing a single happy request instead of the whole system that surrounds it. Take every count from the usage fields the provider returns rather than from a tokenizer estimate, keep your prices in a config file with the date you checked them, and quote the result per accepted outcome rather than per call.

Every price in this guide is yours to supply, deliberately. Provider rates, cache discounts and tier structures change without notice, so any figure printed here would be wrong within months. The structure of the calculation and the places tokens leak out of it do not change, and that is the useful part.

  • usage fieldsthe only trustworthy token count, because schemas, chat templates and scaffolding are billed and your tokenizer estimate misses them
  • 6 metersthe places a system bills tokens even when it looks like one API call
  • k x chunkthe term that dominates retrieval cost, tuned for quality by one person and re-costed by nobody
  • per acceptedthe denominator that matters, because a rejected or retried output is billed in full and delivers nothing

Tokens are not words, and your spreadsheet knows it

A token is a unit produced by a model's tokenizer, roughly a frequently occurring sequence of characters. Common English words often come out as one token, while rare words, proper nouns, identifiers and misspellings split into several. That is why a word count times a fudge factor is a bad estimator, and why the factor that worked on your English prose fails on your JSON payload.

What you sendWhy the count surprises peopleThe cheaper shape
Pretty printed JSON recordsIndentation, quotes and the same field names are billed again on every single record in the batchCompact rows with the schema stated once in the prompt, or CSV with a single header line
UUIDs, hashes, base64 blobsRandom character strings match nothing in the tokenizer's vocabulary, so a short string becomes many tokensPass a small integer index and keep the mapping in your own code, outside the model
Whole documents pasted inHeaders, footers, navigation and repeated legal boilerplate are billed at exactly the same rate as the contentExtract the sections that can carry the answer, and move the parts that never change into the cached prefix
Full conversation historyEvery earlier turn is re-sent on every later turn, so cost grows with conversation length rather than with the current questionRoll older turns into a running summary and keep only the most recent few verbatim
Text in a second languageTokenizer coverage differs by script and by provider, so the same meaning can carry a very different countMeasure your own languages against your own model, then set a per language token budget
Tool and function schemasThey are sent on every call whether or not any tool gets used, and they sit inside the billed inputSplit the tool set by route and expose only the tools a given path can actually call
Every row is a mechanism you can verify on your own data in an afternoon.

Never commit to a number derived from a word count. Take a hundred real inputs, including the longest ones your system has seen, push each through one real call, and read the usage fields on the responses. The gap between estimate and billed count is routinely large enough to change a build decision.

The six meters every language model system runs

A system that looks like one API call bills on six meters at once. A naive estimate reads one of them, usually the payload. Name all six, measure each separately, and the invoice stops surprising anyone.

Framework

The Six Meters

Six separate token meters run in parallel in almost every production system. Tag every model call with the meter it belongs to, and your cost dashboard becomes a design tool instead of an accounting one.

01
Prefix meter

The system prompt, tool and output schemas, few shot examples and any fixed policy text. Fixed per call and billed on every call, so at short input lengths it is most of the bill. This is the meter prompt caching exists to reduce, and the only one you can make close to free.

02
Payload meter

The variable content: retrieved chunks, the document, the record, the ticket history. In a retrieval system this is normally the largest meter at inference time, and its size is set by how many chunks you retrieve multiplied by how large each chunk is.

03
Growth meter

Conversation history and agent loop transcripts, which re-send everything that came before on every subsequent call. Total input across a loop grows roughly with the square of the step count rather than linearly, which is worked through in costing an agent.

04
Output meter

Generated tokens, priced above input tokens on most providers, and produced serially so they dominate latency as well as cost. Reasoning or thinking tokens sit on this meter even though the user never sees them, which makes an unbounded reasoning budget an unbounded bill.

05
Retry meter

Schema validation failures, refusals, timeouts and the repair call that fixes malformed output. A retry re-sends the entire input, so a retry rate of a few percent is a surcharge on every token in the request rather than on the part that failed.

06
Offline meter

Embeddings and re-embeddings, nightly evaluation runs, the judge model in an evaluation suite, classification backfills and synthetic data generation. None of it appears in a per request estimate, and it is the meter most likely to produce an invoice line nobody can explain.

Output tokens are the ones that hurt

Output tokens are usually priced above input tokens, often by a multiple, and they are generated one at a time rather than processed in parallel. So output length is your cost problem and your latency problem at once. Check the current ratio for your model before you decide how hard to work on this, because the value of everything below scales with that ratio.

  • Return identifiers, not prose. If the model is choosing among retrieved passages, have it return chunk ids and assemble the answer in your own code. Otherwise you pay generation rates to have a model retype text you already hold.
  • Return a patch, not the document. A rewritten four thousand token document bills four thousand output tokens. A list of targeted edits bills a fraction, and it is easier to review and to roll back.
  • Constrain the schema. A tight output schema with enumerated values and length limits produces shorter output than free prose, and removes most of the retry meter at the same time. The mechanics are in structured output from LLMs.
  • Stop paying for narration. Asking the model to explain its reasoning on every call bills that explanation at the output rate on every call. If you want reasoning for debugging, sample it on a small share of traffic.
  • Set a maximum output length as a circuit breaker, and log hitting it as an error rather than a normal truncation. An unbounded generation loop is the fastest route to a bill nobody predicted.
  • Budget reasoning tokens explicitly where your model exposes that control. Extended reasoning left on its default is a standing charge on every request, including the easy ones that never needed it.

One trade-off, stated honestly: shorter output genuinely reduces accuracy on some tasks, because the model uses generated tokens as working space. Run both variants against the same test set and compare cost per accepted answer, the only comparison that accounts for the rework a worse answer creates.

Prompt caching rewrites the order of your prompt

Prompt caching bills a repeated leading section of the prompt at a reduced rate. The match is on an exact prefix, which is the single most important property to design around and the one most teams discover late. One changed character anywhere before the cache boundary makes the entire request a miss.

Put the static part first

Order the prompt so everything stable comes before everything variable: system prompt, tool schemas, few shot examples, then the retrieved payload, then the user turn. Teams often build the reverse order because it reads better in code. Retrieved content placed above the fixed instructions guarantees a unique prefix on every request, which turns the discount off without turning the feature off.

Keep everything unique out of the prefix

A timestamp, a request id, a session id, a user name or a randomised greeting inside the system prompt makes every prefix unique. Nothing matches, every call pays the full input rate, and the configuration still says caching is on. Personalisation belongs after the cached section. So does any prompt rebuilt by interpolation in a way that reorders keys between requests.

Two properties decide whether caching is worth anything to you. Providers usually price a cache write differently from a cache read, and entries expire, so a low traffic endpoint can pay the write premium repeatedly and never collect a read. Caching is a volume play. And a deploy that changes one word in the system prompt resets the cache for every user at once, which makes batching prompt changes into scheduled releases a cost decision too.

Check the field, not the flag

The most common caching failure is a system where caching is switched on, the dashboard says so, and the cached token count in every usage response is zero. Something dynamic sits in the prefix. Read the cached input field on real production responses, compute the hit ratio over a day of traffic, and treat any value near zero as a bug rather than as a tuning opportunity. Until cached and fresh input tokens are separated in your accounting, your per request cost figure is wrong in both directions.

Retrieval is where the money actually goes

In a retrieval system the payload meter dominates, and its size is set by two numbers: how many chunks you retrieve and how large each chunk is. Both get tuned for answer quality in one afternoon and neither gets re-costed afterwards. Doubling the retrieved chunk count doubles the payload on every request from that moment on.

Retrieval request cost on your own numbers

Prices are per million tokens in your own currency, taken from your provider's current page. The cache discount is the percentage saved on cached input tokens, and the retry rate is applied to the whole request because a retry re-sends everything.

0Input tokens sent per request
0Cost per 1,000 requests
0Cost per 30 days
0Cost per accepted answer

Look at which term dominates the input line. If the retrieved payload is more than half of it, retrieval quality work is cost work, and the change that pays most is retrieving wide and sending narrow: pull forty candidates, rerank, send the handful that survive. Chunk size interacts with this directly, covered in chunking strategies.

Retrieve more, send it allRetrieve wide, rerank, send few
Input tokens per requestGrows linearly with the chunk count, on every request foreverSet by how many survive the rerank, usually a much smaller number
Extra infrastructureNone, which is the appealA reranking step, priced per query and normally far cheaper per token than generation
Accuracy behaviourImproves, then flattens, then degrades as distractor passages crowd out the relevant oneUsually better at the same or lower token count, because the passage that matters is not buried
LatencyLonger prompts take longer to process and delay the first tokenOne extra hop, then a much shorter prompt
What to measureCost per accepted answer at each setting, not recall aloneThe same, plus the rerank threshold you settled on and why

The meters nobody bills for until the invoice arrives

Every line here is real spend that never appears in a per request estimate, because none of it is triggered by a user. The fix has the same shape each time: give the traffic its own key or metadata tag so it lands as a separate line instead of dissolving into the total.

Hidden meterWhere it comes fromHow to see it earlyWhat makes it grow
Evaluation runsEvery case in the suite is an inference call, run on every merge or every nightTag evaluation traffic with its own key so it appears as a separate line from day oneAdding cases faster than you retire them, and running the full suite on every push instead of on merge
The judge modelScoring with a model on every evaluation case, often the largest model in the whole systemCount judge tokens separately from system tokens in your reportingLong rubrics and full transcripts, both of which are input tokens on every single case
Guardrail and classifier callsAn input filter and an output filter are two extra model calls wrapped around every requestLog them as their own meter rather than folding them into the main callRunning a large model as a guardrail on traffic a small classifier or a regular expression would settle
Re-embeddingA change of embedding model, chunk size or document set means embedding the whole corpus againRecord the corpus token count once, so the price of a re-index is a number you already holdChunk size experiments run against the full production corpus instead of a sample
Retry and repair callsMalformed output triggers a repair call that re-sends the entire inputTrack retries per thousand requests as a first class metric next to latencyFree form prompts with no schema, and schemas the model structurally cannot satisfy
Development and staging trafficEngineers testing, load tests, and a loop left running in a branch over a weekendSeparate keys per environment with a hard spend cap on eachNo cap, no alert, and a retry loop with no ceiling

Put a cost line on every request

Provider dashboards aggregate at exactly the wrong level, by key and by day, when what you need is by unit of work and by meter. Emit a cost line per request into the same store as your traces. It is a small piece of code and it repays itself the first time somebody asks why the bill moved.

Per request cost ledger, provider neutralpython
# Prices live in config and carry the date they were checked. Fill these
# from your provider's current pricing page before you trust any output,
# and set them per million tokens in whatever currency you are billed in.
PRICES = {
    "checked_on": "2026-08-19",
    "unit": "per million tokens",
    "models": {
        "small": {"in": 0.0, "cached_in": 0.0, "out": 0.0},
        "large": {"in": 0.0, "cached_in": 0.0, "out": 0.0},
        "embed": {"in": 0.0, "cached_in": 0.0, "out": 0.0},
    },
}

METERS = ("prefix", "payload", "growth", "output", "retry", "offline")


def cost_of(usage, model, meter, prices=PRICES):
    """usage must be the provider's own usage object from the response.
    A client side tokenizer estimate will not match what you are billed."""
    p = prices["models"][model]
    cached = usage.get("cached_input_tokens", 0)
    # providers differ on whether input_tokens already excludes cached tokens.
    # verify against one real invoice line before you trust this subtraction.
    fresh = max(0, usage["input_tokens"] - cached)
    out = usage["output_tokens"] + usage.get("reasoning_tokens", 0)
    return {
        "model": model,
        "meter": meter,
        "cached_in": cached,
        "fresh_in": fresh,
        "out": out,
        "cost": (fresh * p["in"] + cached * p["cached_in"] + out * p["out"]) / 1_000_000,
        "price_checked_on": prices["checked_on"],
    }


def request_ledger(request_id, unit_of_work, calls, accepted):
    """calls: [{"usage": {...}, "model": "large", "meter": "payload"}, ...]"""
    lines = [cost_of(c["usage"], c["model"], c["meter"]) for c in calls]
    total = sum(l["cost"] for l in lines)
    billed_in = sum(l["cached_in"] + l["fresh_in"] for l in lines) or 1
    return {
        "request_id": request_id,
        "unit_of_work": unit_of_work,          # one answered question, one parsed invoice
        "lines": lines,                        # one line per model call, tagged by meter
        "cost_total": round(total, 6),
        "cost_per_accepted": round(total, 6) if accepted else None,
        "cache_hit_ratio": sum(l["cached_in"] for l in lines) / billed_in,
        "retries": sum(1 for c in calls if c["meter"] == "retry"),
        "accepted": accepted,
    }

Three fields do the real work. The meter tag turns a total into a diagnosis, because a jump in the offline meter and a jump in the payload meter have different causes and different fixes. The cache hit ratio catches a broken prefix the day it breaks rather than at month end. The checked date stops a stale rate propagating quietly into a business case.

Terms to be precise about

Definitions worth getting exactly right
Token
The unit a model's tokenizer produces from text, usually a frequently occurring sequence of characters rather than a word. Token counts are specific to a model family, so a count taken from one provider's tokenizer does not transfer to another, and only the usage fields returned with a response reflect what you are actually billed.
Prompt cache hit
A request whose leading section exactly matches a previously cached prefix and is therefore billed at a reduced input rate. The match is on an exact prefix, so a single changed character anywhere before the cache boundary turns the whole request into a miss.
Output token
A token the model generates. On most providers it is priced above an input token, and because generation is serial rather than parallel, output length drives latency as well as cost. Any control over response length is therefore a control over two budgets at once.
Reasoning tokens
Output a model generates as intermediate working, billed at the output rate whether or not it is ever shown to a user. A system that enables extended reasoning without setting a budget is paying generation rates for text nobody reads.
Effective input rate
The blended price actually paid per input token once cached and fresh tokens are separated. Quoting a single input rate for a system with prompt caching overstates cost on cached traffic and understates it on cold traffic, sometimes badly enough to invert a build decision.
Cost per accepted outcome
Total token spend for one unit of work divided by the fraction of outputs accepted without rework. It is the only per unit figure that survives a comparison between two models with different accuracy, because a cheaper model that is wrong more often is billed twice and delivers once.

Before you quote a number to anyone

Token estimate sanity check
0 of 10 done
The number with a shelf life

A token estimate ages faster than almost anything else in an engineering plan, because rates, tiers, cache rules and model families all change without warning. Build the model so that a price change is one edit in one config file, put a reminder in the calendar to rerun it quarterly, and never let a spreadsheet from last quarter decide this quarter's architecture. If you would rather have the whole cost model built alongside the system, that is part of how we scope custom LLM applications.

Questions readers ask next

How do I calculate LLM token cost?
Multiply fresh input tokens by your input rate, cached input tokens by the cached rate, and output tokens by the output rate, all per million. Add the tokens consumed by retries, guardrail calls and offline evaluation runs, then divide by the fraction of outputs you accept without rework. Take every count from usage fields on real responses, and quote the median and the 95th percentile so the tail stays visible.
Why is my token bill higher than my estimate?
Almost always one of five reasons. The estimate came from a word count rather than real token counts. It priced the payload and ignored the fixed prefix billed on every call. It ignored retries, which re-send the entire input. It ignored offline traffic from evaluation suites, judge models and re-embedding jobs. Or prompt caching is enabled in configuration but never hitting, because something unique sits inside the prefix.
Are output tokens more expensive than input tokens?
On most providers yes, often by a multiple, though the exact ratio changes with the model and the pricing round, so check your own current rate. The practical consequence is that shortening responses saves more than shortening prompts. Return identifiers instead of prose, return targeted edits instead of rewritten documents, constrain the output schema, and set an explicit budget for reasoning tokens, which bill at the output rate even though nobody reads them.
Does prompt caching actually save money?
It does when your prefix is large, stable and hit often. It saves nothing on a low traffic endpoint where entries expire between requests, and it can cost more than it saves if your provider charges a premium for writing entries you never read back. It saves nothing at all if anything unique sits in the prefix, which is the common failure. Measure the cached token field on production responses, not the configuration flag.
How much does RAG cost per query?
The dominant term is the number of chunks you send multiplied by the tokens per chunk, plus your prefix, plus the output. Run those four numbers through your own rates rather than trusting any published figure, because retrieval depth varies enormously between systems. If the retrieved payload is more than half the input, the cheapest improvement is usually reranking: retrieve a wide candidate set, then send only the passages that survive scoring.
Should I use a smaller model to cut token costs?
Sometimes, and the honest test is cost per accepted outcome rather than price per token. A smaller model that fails validation more often triggers repair calls that re-send the whole input, needs more human review, and can need more retrieved context to reach the same answer. Run both over the same test set, count retries and acceptance for each, then compare. Routing easy cases small and hard cases large usually beats picking one.
Cite this

ChatGPTalker. "Token Costs: The Arithmetic Nobody Shows You." chatgptalker.com, 2026-08-26. https://chatgptalker.com/guides/token-cost-arithmetic/

Rather have it built than read about it?

Send the process you want automated. You get a scoped plan back, with the build shape, the stack and a realistic timeline.

Start a project