Per-user AI budgets 

The tx_nrllm_user_budget table caps per-backend-user AI spend independently of the per-configuration daily limits on tx_nrllm_configuration. A user request must clear BOTH layers: any limit on the preset they chose AND any limit on their personal budget record.

What a budget caps 

Each row in tx_nrllm_user_budget binds to exactly one be_user and defines six independent ceilings. 0 on any axis means "unlimited on this axis".

Field Unit Reset cadence
Max Requests/Day count Every day at 00:00 server-local time.
Max Tokens/Day count Every day at 00:00 server-local time.
Max Cost/Day ($) USD Every day at 00:00 server-local time.
Max Requests/Month count First of the month, 00:00 server-local time.
Max Tokens/Month count First of the month, 00:00 server-local time.
Max Cost/Month ($) USD First of the month, 00:00 server-local time.

Usage is aggregated on demand from tx_nrllm_service_usage — the same table the UsageTracker already writes to per request — so there is no second write per request and no way for a separate counter to drift away from the source of truth.

Creating a budget 

Budget records have rootLevel = -1, so admins can create them at the TYPO3 root (pid = 0) or on any regular page. Keeping them at the root is the convention because budgets are site-wide admin concerns, not page-scoped content; the recipe below follows that convention.

  1. Open Web > List in the root (page UID 0) — or on the page where you keep other cross-site configuration records.
  2. Click Create new record.
  3. Choose LLM User Budget.
  4. Pick the backend user, set the ceilings, toggle Enforce this budget on.
  5. Save.

How the check runs 

Before dispatching a request the consuming extension calls NetresearchNrLlmServiceBudgetService::check(). The service:

  1. Returns allowed when the user has no budget record, when Enforce this budget is off, or when every ceiling is 0.
  2. Aggregates today's usage and this month's usage in a single database roundtrip.
  3. Evaluates the daily window first; the monthly window only if the daily window passes.
  4. Adds +1 request and +plannedCost to the usage figures before comparing, so a user at exactly the limit is still allowed one more call.

The returned BudgetCheckResult names which bucket was tripped (exceededLimit as a stable machine key, plus a human-friendly reason string suitable for log output or caller-side wrapping).

Budgets vs. configuration limits 

Both layers persist but cap different things:

Axis Configuration daily limits Per-user budgets
Bound to a preset (tx_nrllm_configuration) a backend user (tx_nrllm_user_budget)
Question answered "Can ANY editor keep using this preset today?" "Can THIS editor keep spending this month?"
Windows daily daily AND monthly
Dimensions requests, tokens, cost requests, tokens, cost
Both must pass yes yes

See ADR-025: Per-User AI Budgets for the full design rationale, including the alternatives (counter table, group-level budgets, auto-throttling) we considered and why they were rejected.