Every product built on a language model receives its supplier invoice in tokens, and the cheapest decision available is to pass the same unit onward to the customer. It is a few lines of billing code, and in most stacks it is the default nobody argues with. It also settles three things that are expensive to reverse: what your customer can forecast, who pays for your defects, and which way your own engineering incentives point.
MONEY-5. The pricing metric scales with the customer’s own success.
The method in one line: meter the unit your customer would recognise on a receipt, count it in one ledger that both the meter and the refusal read, and price it against the tail of its cost distribution rather than the average.
A token count is a fact about your implementation
A token measures how your system did the work, not what the customer received. Add prompt caching and the number falls, so an identical deliverable bills lower this month than last. Add a verification pass that makes the output better and the number rises, so the customer pays more for an improvement they did not ask for and cannot see. Route the routine eighty per cent of calls to a cheaper model and the count barely moves while your unit cost halves, which is the same objection from the other side: the token count tracked neither their outcome nor your cost. Billing on tokens publishes your architecture as a price, and then makes every change to that architecture a change to the bill.
The sharper consequence is what happens when the work goes wrong. An agent that loops, retries, re-reads a file it has already read, or abandons a job halfway has consumed tokens, and on a per-token bill the customer is holding that line item. That is the cost of your defects, itemised on the invoice of the only party who cannot fix them. Measure the size of it before deciding anything else:
select outcome,
count(*) as jobs,
sum(input_tokens + output_tokens) as tokens,
round(100.0 * sum(input_tokens + output_tokens)
/ sum(sum(input_tokens + output_tokens)) over (), 1) as pct
from job_runs
group by outcome
order by tokens desc;If that query cannot run because outcomes and token counts are recorded in different places, that is the more urgent finding. A usage ledger that cannot say which units produced something is a ledger you cannot price from, whichever unit you end up choosing. One append-only row per billable action, written by the code that performs the action, is the whole requirement.
Measure the variance before promising a price
Per-unit pricing is an agreement to absorb variance the customer would otherwise carry. Whether that is a good trade for you is an arithmetic question, and the arithmetic is one query against the units you already record.
select count(*) as jobs,
percentile_cont(0.5) within group (order by tokens) as p50,
percentile_cont(0.75) within group (order by tokens) as p75,
percentile_cont(0.95) within group (order by tokens) as p95,
max(tokens) as worst,
avg(tokens) as mean,
stddev_samp(tokens) / avg(tokens) as cv
from delivered_jobs;Across 128 completed agent jobs in one production workload, that query returns a distribution wide enough to settle the argument on its own.
| Measure | Tokens |
|---|---|
| Median | 28,991 |
| 75th percentile | 95,715 |
| Mean | 135,132 |
| 90th percentile | 390,782 |
| 95th percentile | 746,660 |
| Worst | 1,726,292 |
For the customer that table is the case against per-token billing on its own. Two requests that read identically when they are written differ by more than an order of magnitude in what they consume, so nobody can forecast a bill, approve a budget, or explain a variance to a finance team. The distribution is also skewed hard enough that intuition fails on it: the mean sits above the 75th percentile, and only 30 of the 128 jobs exceed it.
For you the same table is an exposure, and reading it correctly matters more than reading it dramatically. The mean is what sets your margin once volume is large, because per-job spread pools across many jobs: the standard deviation of a total grows with the square root of the count, so a busy account converges on the mean and a quiet one does not. The tail is what sets your exposure wherever the count is small, which is every low-volume plan you sell and every account in its first month. Run the same query a second time over the monthly total per account rather than per job, and price the plan against that. A per-job 95th percentile is a number nobody is ever billed for.
A bill the customer cannot forecast is a bill they have to supervise.
Choosing the unit
The unit is right when the customer can count it before buying and recognise it afterwards. That is a stricter test than it sounds, and most candidate units fail on at least one of five properties.
- It is binary. It was produced or it was not, and both parties can look at the same artifact and agree which.
- The customer asked for it by name. Nobody orders a token: they order a document, a clip, a seat, a processed record.
- Its price does not depend on difficulty the customer cannot see. Scope they can see is allowed to be a different unit at a different price. Internal execution cost is yours to carry, and a unit whose price follows it is a token under another name.
- It can be refused before it starts. A unit you can only meter after the compute is spent is a report, not a limit.
- It can be stated as a number in a sentence. "Two hundred a month" has to mean something to a buyer who has never read your architecture.
Where the work is homogeneous, per item is the answer. Where the value is somebody’s time, per seat is. The hard case is a deliverable whose supplier cost scales continuously inside it, such as a video clip that might be four seconds or sixty. There are two honest resolutions and they exclude each other: fix the size of the deliverable so that one clip is one unit at one price, or meter the continuous quantity and stop selling clips as a unit at all. Selling both is the defect the next section catches.
Three checks that make per-unit pricing survivable
Absorbing the variance is the deal you are offering, and it is only a good deal if all three of these hold.
- Price the mean for margin and the tail for exposure, and read both at the level you actually bill. Aggregate to the billing period per account before reading either number: per-job spread pools out across a busy account and does not pool out on a small plan, which is how one product stays profitable on its largest tier and loses money on its smallest.
- Cap the unit so that it stays one unit. An unbounded agent loop is not a unit of work; it is an open account with a product name on it. Across the same 128 jobs the median ran 6 rounds and the longest ran 68, and rounds correlate with consumption at 0.74, which is the largest single lever you hold and still explains only about half the variance. Input size and the number of artifacts produced are most of the remainder, so the ceilings go on all three, and each one refuses in words rather than truncating in silence.
- Prove that every allowance you advertise is reachable. A unit that can only be produced inside another metered unit is capped by that other unit, and the arithmetic stops being obvious the moment a plan carries more than two numbers.
The third one earns a check rather than a habit, because its failure mode is silent. Nothing errors, nothing alerts, and the plan simply advertises an amount that cannot be consumed. A plan may not sell two allowances that are secretly one.
// A unit produced only INSIDE another metered unit is capped by it.
// `per` is how many children ONE parent yields: a build produces up to
// six images; one second of video buys a quarter of a four second clip.
const NESTED = {
images: { parent: 'builds', per: 6 },
clips: { parent: 'video_seconds', per: 0.25 },
}
for (const plan of plans) {
for (const [unit, n] of Object.entries(NESTED)) {
const sold = plan[unit], cap = plan[n.parent]
if (sold == null || cap == null) continue
const reachable = Math.floor(cap * n.per)
if (sold > reachable) {
console.log(`${plan.id}: sells ${sold} ${unit}, `
+ `but ${cap} ${n.parent} reaches ${reachable}`)
}
}
}Run against a real plan table of seven plans it takes 0.14 milliseconds and reports two allowances that cannot be consumed: one plan selling 3 clips against a monthly allowance of 0 seconds, and one selling 15 clips against 15 seconds, which at a four second minimum reaches 3. That is the ordinary shape of the defect. A capability gets remetered in a different unit, the old column stops being read, and its numbers stay in the table looking exactly like a promise. Nothing errors, because nothing is wrong with the code. What is wrong is the arithmetic between two columns, and no type system checks arithmetic between two columns.
One ledger, or the product tells three stories
The number on the customer’s usage card, the number the gate refuses on, and the number that reaches the invoice have to be one number, read from the same rows. Computed separately they will diverge, and a customer who watches a card read 40 of 60 and is then refused on the 41st has not been misled by a person. They have been misled by arithmetic, which is worse, because there is nobody to appeal to.
Record usage in the supplier’s own units as it happens and keep prices in their own table, married at read time. That keeps your internal cost view correct through a supplier’s rate change with no migration behind it. Keep it out of customer billing, where a rate row carries the dates it was in effect and a closed period is priced at the rate that applied then, never at today’s.
The two ledger operations then have opposite failure rules, and collapsing them into one is a defect either way. The gate’s READ blocks: when the allowance cannot be read, refuse the job and say so retryably, because failing open reopens the door the gate exists to close. The cost pen’s WRITE does not block: a failed write is logged loudly and the work proceeds, because a lost accounting row is recoverable and a lost deliverable is not. Get that pair the wrong way round and you ship either a product that stops whenever the accounting database is slow, or a quota anybody can bypass by making it slow.
The limits themselves belong in rows rather than in deployed constants. A cap is a tuning lever; it moves when the cost of the underlying capability moves, and a lever that requires a deploy is a lever nobody pulls in the week it matters.
Never charge for a unit you did not deliver
The rule is mechanical: the counter increments on the delivered artifact, never on the accepted request. A job that failed on your side, and a job your retry logic ran three times before it succeeded, cost the customer exactly what a job that never started costs them, whatever they consumed. This clause is what makes per-unit pricing worth its variance cost, because it puts the price of every defect on the only party able to remove it.
A cancellation is the one case that needs stating separately, because the generous version of the rule can be farmed. Price a cancelled job by what had already been delivered when it was cancelled, not by the fact that it was cancelled. Zero-rating every cancellation invites the obvious move: start expensive work, read the intermediate output as it streams, and cancel before the artifact is written.
The corollary catches teams a second time. When a customer reports that the output was wrong and asks for a correction, do not spend their main unit on it. Meter corrections on their own line, with a limit set high enough that an honest hand never reaches it, and treat that limit as a wall against loops rather than as a meter anybody watches. Charging a unit to correct your own output teaches customers to stop reporting defects, and those reports are worth more than the compute they cost.
That lane stays cheap only if it is structurally incapable of becoming the main one. Bind it to a single pass over an artifact that already exists, with no new deliverable and a ceiling on input size, so that a request which expands scope does not fit through it and has to be ordered as a unit. A correction channel defined by nothing more than the customer calling it a correction is a free tier anybody can enter by choosing a word.
When a limit is genuinely reached, refuse in a complete sentence that names the plan, the cap, the amount consumed, the reset date, and what still works without it. A refusal reading only "limit reached" converts a pricing decision into a support ticket.
What to do this week
- Run the outcome query against your usage ledger. If it will not run, fix the ledger before touching the price.
- Run the distribution query twice, once per job and once over the monthly total per account. The first says whether your unit is stable enough to sell; the second is the one your price has to survive.
- Write down the unit a customer would name in a sentence about their day, then test it against the five properties above.
- Put an explicit ceiling on rounds, on items per job and on input size, and make each ceiling refuse in words.
- Run the consumability check across your plan table, including the metered columns nothing reads any more.
The general form is older than any of this. A price is a promise about a unit, and the unit has to be one the buyer can count and the seller can control. Tokens are a unit the buyer cannot count and the seller only partly controls, which is what makes them the right unit for a supplier’s invoice and the wrong one for a customer’s.
This post argues MONEY-5 from THE PLATFORM LAWS, the standing rules for anything Wavn, Inc. builds. Related reading: our principles, how we handle AI output and the record.