Model usage in CodeLynq is paid from prepaid credit. The subscription pays for the platform; the credit pays for what the models cost, which varies by more than an order of magnitude between a dependency bump and a scaffold of a new service. Each run is charged after it finishes, because its cost cannot be known before, and when the balance reaches zero new runs are refused while runs already in progress are allowed to finish.
We thought that was a spending control. It is not. It fires when the money is gone. A team that tops up a few hundred euros can spend all of it in an afternoon, and the first signal is the empty balance.
The two obvious answers are both wrong
The first is to approve every run. It sounds responsible and fails within a week: when every run asks, the approver stops reading and clicks, and an approval nobody reads controls nothing. The second is to approve nothing and look at the invoice, which is how people end up afraid of their own tools.
What a budget holder actually wants is narrower: ordinary runs go through, unusual ones ask first, and some things never happen without a deliberate change of mind.
Three zones and a monthly ceiling
So an organisation admin can set three amounts under spend limits:
- Runs freely up to. Below this estimate, a run starts without asking anyone.
- Never more than, per run. Above this, the run is refused, with a message suggesting the task is split or the limit raised.
- Per month, across every project. Once this month's charges reach it, new runs are refused until it is raised.
Between the first two is the zone that matters: the run is created, costed and held. It is not queued, so no worker can pick it up, and it is not failed, because nothing went wrong. Organisation admins are notified, and the run page shows the estimate, that nothing has started and nothing has been charged, and two buttons.
All three limits are off until someone sets them. A cap that appeared by surprise would block work nobody chose to block, so an organisation that never opens the screen behaves exactly as before.
Where the estimate comes from
The estimate is the 90th percentile of what comparable runs in the same project actually cost: nine out of ten stayed under it. It is narrowed to the same task type once there are at least three such runs, because a chore rarely costs what a feature costs, and it is converted with the same arithmetic as the charge at the end, so the figure an admin approves is on the same basis as the one they pay.
The 90th percentile is deliberate: conservative enough to catch a genuine outlier without stopping ordinary work. It is a nearest-rank figure from real runs, not an interpolation, because a small sample dressed up with decimals is false precision.
With no history there is no estimate, and the run is allowed. Blocking on a number we made up would stop every first run on a new project, which is the worst moment to put a wall in front of someone.
The same history drives the forecast next to the run button, so the typical cost of this kind of work is visible before anyone presses it, held or not.
Details that turned out to matter
- Only organisation admins approve. Owning the project is not enough: any member can create a project and own it, which would let them wave through their own held run and make the threshold decorative.
- Limits are checked again at approval. A run held overnight may sit behind a monthly cap that was reached in the meantime. Approving it then would spend money the organisation has already said it does not want to spend.
- Declining is not failing. A declined run is cancelled with a note saying who declined it, and the task stays where it was, so it can be split and tried again.
- Unattended runs do not wait. A run started automatically from a monitoring alert is stopped by "needs approval" as well as by "refuse". A run that would need a person to approve its cost is exactly one that should not start at three in the morning.
- Self-hosted runs are exempt. They run on your machines and are not charged to the credit, so there is nothing to approve.
A trap in the cost columns
Runs already had a cost estimate column. It holds what the model provider charged us, in dollars, worked out from token counts. The approval figure is what the customer pays, in euros, after conversion. Reusing the existing column would have silently mixed two currencies and two parties' money in one field, and every comparison against a limit would have been quietly wrong. The approval figure got its own column, and we now name any cost field after whose money it is and in which currency.
What it does not do
- The estimate does not read the task. Two features in the same project get the same estimate, whatever their specs say.
- A 90th percentile is not a maximum. One ordinary run in ten will cost more than its estimate, and the per-run limit is checked against the estimate, not the final bill.
- The monthly ceiling is exact, because it counts charges rather than forecasts, but it can only stop the next run. The one that crossed the line has already run.
- Only runs with a measured cost feed the estimate. Claude Code reports one; runs on agents that do not report a cost are not part of the basis.
A sensible first setting is a per-run approval amount a little above what your typical run costs, read off the forecast, and a monthly ceiling at the budget you would be uncomfortable explaining. More on how runs are priced and routed on cost control and in paying Opus prices to bump a dependency.