AI·Cost
What an LLM feature actually costs
Per-million-token pricing looks cheap until a chat feature resends its whole history on every turn. Here is the arithmetic that turns a price per million into a monthly bill, and the growth curve that catches people out.
Before you start
- A rough idea of your prompt size and request volume
Model pricing is quoted per million tokens, which is a unit chosen to sound small. Three dollars per million is a real price and it is also completely uninformative until you know how many tokens one use of your feature takes.
Almost every unpleasant surprise in an AI bill comes from the same two places: the request is bigger than anyone estimated, and a conversation resends everything that came before it.
The unit you actually pay in #
Two numbers per request, priced separately, because output costs several times more than input:
≈1.3
Tokens per English word
So 1,000 words is roughly 1,300 tokens
4–5×
Output vs input price
Typical multiplier across providers
in + out
Billed per request
System prompt counts, every time
The token ratio is an approximation for English prose. Code, JSON and non-Latin scripts tokenize less efficiently, sometimes much less, so measure your own payloads rather than trusting a ratio.
Your system prompt is part of the input on every single call. A 400-token system prompt on a million requests is 400 million input tokens that produced no user-visible value, and at mid-tier pricing that is over a thousand dollars a month to say the same thing repeatedly.
The arithmetic #
One formula, and it is worth writing down rather than eyeballing:
// Prices are per million tokens, so the divisor is 1e6.
const requestCost = ({ inputTokens, outputTokens, inputPrice, outputPrice }) =>
(inputTokens / 1e6) * inputPrice + (outputTokens / 1e6) * outputPrice;
// A 1,500-token prompt, a 400-token answer, at $3 / $15 per million.
requestCost({
inputTokens: 1500,
outputTokens: 400,
inputPrice: 3,
outputPrice: 15
});
// 0.0105 — just over one cent per request.
One cent is easy to dismiss. Multiply it by the volume you are actually planning for:
| Requests / month | $0.25 / $1 per M | $3 / $15 per M | $15 / $75 per M |
|---|---|---|---|
| 10,000 | $8 | $105 | $525 |
| 100,000 | $78 | $1,050 | $5,250 |
| 1,000,000 | $775 | $10,500 | $52,500 |
These are round-number price points spanning the range providers charge, not quotes from any specific provider. Substitute the rates on your own invoice.
A table rather than a chart, deliberately: the values span four orders of magnitude, and on any bar chart with a single honest zero-based axis the $8 bar is one pixel next to the $52,500 one. A chart that hides five of its nine numbers is worse than the table it replaced.
The spread across price points is 65×. That is the single largest lever you have, and it is worth knowing which parts of your feature genuinely need the expensive model before assuming all of them do.
The curve nobody budgets for #
Here is the one that catches people. A chat feature is stateless underneath: the model has no memory, so to continue a conversation you resend the entire conversation. Every turn.
Turn one sends a system prompt and one message. Turn twenty sends the system prompt and nineteen previous exchanges. The input per turn grows linearly, so the total grows with the square of the conversation length.
- Cumulative input
- Cumulative output
Simulated from the stated message sizes, resending full history each turn. Output rises in a straight line because each turn produces one reply; input curves because each turn carries every turn before it.
View data as a table
| Turn | Cumulative input | Cumulative output |
|---|---|---|
| 1 | 520 | 320 |
| 2 | 1,480 | 640 |
| 4 | 4,720 | 1,280 |
| 6 | 9,720 | 1,920 |
| 8 | 16,480 | 2,560 |
| 10 | 25,000 | 3,200 |
| 12 | 35,280 | 3,840 |
| 14 | 47,320 | 4,480 |
| 16 | 61,120 | 5,120 |
| 18 | 76,680 | 5,760 |
| 20 | 94,000 | 6,400 |
Output is a straight line. Input is a curve, and by turn twenty it is fourteen times larger than output. Compare that conversation against a hypothetical one where history was not resent:
| Input tokens | Cost at $3 / $15 | |
|---|---|---|
| History resent each turn | 94,000 | $0.378 |
| History not resent | 10,400 | $0.127 |
Nine times the input tokens, three times the total cost, for the same twenty replies. And that is a short conversation. At fifty turns the multiple is far worse, because the growth is quadratic and your intuition is linear.
Watch out
This is also how you hit a context limit without sending anything large. Nobody sent a big message. The conversation simply accumulated, and turn forty was rejected for a length nobody typed.
Three things actually help, in descending order of effect:
- Cap the history. Send the last N turns, not all of them. Most conversations do not need turn three by the time you are on turn thirty.
- Summarise the middle. Replace older turns with a short running summary. The cost of producing that summary is repaid within a few turns.
- Use prompt caching. Providers that offer it charge a fraction of the input rate for a prefix they have seen before, which is exactly the shape of this problem, since the system prompt and early history are identical every turn. It changes the constant, not the curve, so combine it with capping rather than relying on it alone.
Prompt size matters more than you think #
Because input is billed per token and there is a lot of it, the size of what you send dominates the bill long before the choice of model does at the cheap end:
Arithmetic on the formula above. One price point rather than three, because the tiers differ by up to 65× and plotting them together on one axis would flatten the cheapest into the baseline. The shape is the same at every tier; only the multiplier changes.
View data as a table
| Prompt tokens | Cost per 1,000 requests ($) |
|---|---|
| 500 | $7.50 |
| 2k | $12 |
| 4k | $18 |
| 8k | $30 |
| 16k | $54 |
| 32k | $102 |
A 500-token prompt costs $7.50 per thousand requests. The same feature with a 32,000-token prompt costs $102, a fourteen-fold increase for output the user may not notice is any better.
Retrieval systems are where this goes wrong quietly. Stuffing twenty retrieved documents into a prompt because the context window allows it turns a 500-token request into a 32,000-token one, and the chart above shows what that does. Retrieve fewer, better chunks.
Before you ship #
Do these three things and you will not be surprised:
- Count real tokens, not estimated words. Use your provider's tokenizer on ten actual payloads, including your worst case. The ratio for your data will not be the ratio for prose.
- Log input and output tokens per request from day one. Every provider returns them in the response. Without that log you cannot tell an expensive feature from a popular one.
- Set a spend limit at the provider. A retry loop that runs unattended overnight is a real failure mode and the limit is the only thing that stops it.
Then run the arithmetic at ten times your expected volume. If that number is survivable, ship it. If it is not, the problem is in the prompt size or the model choice, and both are much cheaper to change now than after launch.