Per-Client LLM Budgets
Every AI feature in Proxima Console — natural-language search translation, AI chat, and L1 triage — spends LLM tokens, and that spend is billed against a shared platform key. Per-client LLM budgets let a super-admin cap how much a single client (project) can consume, so one noisy or runaway tenant can't drive up cost for everyone. It is a cost control, not a security boundary.
Each client gets two independent knobs:
- Monthly token budget — the total tokens the client may consume in a calendar month. The counter resets at the start of each UTC calendar month.
- Burst tokens/min — a short-window throttle: the tokens the client may consume within any one-minute window. This catches a runaway loop or an abusive spike long before the monthly budget would notice.
For either knob, 0 or blank means unlimited. A client with both left blank is completely
unmetered (and Proxima skips the budget bookkeeping entirely for it).
Who can set them
Budgets live under the client's features.llm settings and are editable only by
super-admins, in the LLM budget section of the client page's tier/features panel. Clients
cannot see or raise their own budget — it is a platform-operator control.
To set a budget:
- Open the client's detail page as a super-admin.
- In the Features panel, find the LLM budget section.
- Enter a Monthly token budget and/or a Burst tokens/min (leave blank for unlimited).
- Save. Changes take effect within about a minute (limits are cached briefly to keep the enforcement path off the database).
What happens when a budget is hit
Enforcement is applied per AI surface, and each surface degrades gracefully rather than hard-failing — the goal is to stop the spend, never to break the product:
| Surface | Behavior when the budget is reached |
|---|---|
| NL→PQL translate (the search bar's plain-English mode) | Soft-fails. The request returns a normal 200 with error="budget_exceeded" and a message telling the user to type PQL directly. No model is called. |
| AI chat | Returns 429 with a "Monthly AI budget reached for this project" error. The message is not sent to the model. |
| L1 triage | The alert is still raised. Triage simply skips the AI investigation — the alert group is left fully intact, still pages through its normal notification fan-out, and just carries no AI analysis. Operators lose the AI write-up for that alert, not the alert itself. |
Because the monthly and burst counters are checked before the paid call and the tokens are recorded after it, a single call that is currently under the cap is always allowed to complete — so a brief burst can slightly overshoot the configured budget. This is intentional: the budget is a soft ceiling, not a hard transactional limit.
Viewing usage
The client page shows an "AI usage this month" line — this calendar month's consumed tokens against the configured monthly budget (or "Unlimited").
The same data is available from the API:
GET /api/v1/clients/{id}/llm-usage
{
"data": {
"monthly_tokens_used": 128450,
"monthly_token_budget": 500000,
"burst_tokens_per_min": 2000
}
}
monthly_tokens_used counts this UTC month's triage + chat tokens (summed across
input/output). Access requires super-admin or clients:read on that specific client.
The usage line reflects triage + chat only. NL→PQL translate spend still counts toward the enforced budget (it increments the same monthly counter), but translate calls do not write a stored ledger row, so they are not included in this displayed figure. Because translations are single, cheap completions this gap is small — but it means a client can be throttled slightly before the displayed "used" reaches the budget.
It fails open (by design)
Per-client budgets are a soft, fail-open cost control:
- If the budget backend (Valkey) is unreachable, or a client's limit config can't be read, the check fails open — the AI call is allowed, and a rate-limited warning is logged. An infrastructure blip never takes AI features offline.
- As noted above, a brief burst can slightly overshoot the configured budget because the cap is checked before a call and billed after it.
Contrast this with the authentication rate limiters, which deliberately fail closed. Budgets protect cost, not security, so the safe default is "allow and log".
Observability
Two Prometheus counters expose budget activity (both labeled only by bounded enums — no per-client label; per-client consumption is read from the usage endpoint above):
| Metric | Labels | Meaning |
|---|---|---|
proxima_llm_budget_denied_total | surface (translate/chat/triage), limit (monthly/burst) | LLM calls denied because a client hit its monthly budget or per-minute burst limit — broken down by surface and which limit tripped. A rising rate means clients are hitting their caps. |
proxima_llm_tokens_consumed_total | surface (translate/chat/triage) | Tokens recorded against per-client budgets after each call completes, by surface. |
See also
Per-client token budgets are one of several limits in the platform. For the full picture — HTTP request limits, the AI-chat rate limit, and how they're enforced — see Rate Limiting.