budgets, and every request under that policy must fit each of them. A budget is a cap, not a balance: no money moves, nothing is topped up, and unused room does not carry over.
Fields
A budget is owned by the system, a team, a project or a user, and may be linked by policies of that scope, as described in What a policy holds.
How spend counts
A request’s cost is computed from the provider’s reported token counts and the binding’s pricing, and charged to every budget on its ladder after the response ends. Spend counts in the period the charge lands in. Like a rate limit, a budget counts per bound account. A policy bound to a team’s account gives the team one spend count; the same policy bound to two projects’ accounts gives each project its own. Linking one budget from the policies of two accounts gives each account its own count of the same cap. A link withshared: false gives every lane under the bound account its own count instead, so a team policy can cap each member at the same amount; see Shared and per-lane counting.
At each period start the count begins again from zero and the full cap is available. Editing a budget mid-period:
- Raising or lowering
amountUsd, or switchingmode, keeps the count. A raised cap gives room at once; a cap lowered below what is already spent refuses until the period ends. - Changing
periodstarts a new count.
RELAY_STATE_BACKEND=memory, each pod counts its own spend, so every pod allows the full cap.
Hard and alert
A hard budget is checked when the request is admitted: once the period’s spend has reached the cap, the request is refused. Requests already in flight are charged when they finish, so spend can pass the cap by what those requests cost. A refusal by a budget on a caller rung (team, project or lane) answers:Retry-After is the time left until the next period starts.
A budget on an upstream rung (a provider account) caps the total spend through that account’s host keys, whoever the caller is; linked with shared: false, it caps each caller lane’s spend through them. When it is spent, Relay skips that host key the way it skips one over an upstream rate limit, and the request fails with 429 rate_limit_exceeded only when no other key can serve it.
An alert budget is never checked at admission. Both modes report the charge that takes a budget to its cap, once per budget and period, in the relay_limits_budget_crossings_total counter, labelled by rung and mode.
Models without pricing
A budget can only count what has a price. While any budget applies to a request, on any rung, a binding that has no pricing is refused with403 unpriced_under_budget, naming the rung and policy whose budget applies. Requests for priced models under the same policy are unaffected, and so are unpriced models for callers with no budget on their ladder.
To allow such a model under a budget, add a pricing for its binding (/api/pricings). Pricing is shared catalog data, so under RELAY_AUTHZ=rbac writing it takes the admin or catalog-editor role; see Ownership.