AI usage quota

Per-tenant, per-model usage budgets for AI inference endpoints. OWASP LLM Top 10 2025 ranks LLM10: Unbounded Consumption — the class that includes "denial of wallet" (DoW), where an attacker drives a high volume of pay-per-use inferences until the bill itself becomes the attack — as a top application risk. A single misbehaving (or compromised) tenant can saturate context windows, exhaust GPU minutes, or run up an unbounded cloud-inference bill long before a human notices.

This primitive enforces a hard ceiling per (tenant, model, dimension, period):

- dimension — what is being metered: "tokens" (context + completion tokens), "requests" (inference calls), "cost-usd" (provider spend), or "compute-hours" (GPU / accelerator time). - period — the budget window, calendar-aligned in UTC: "second", "minute", "hour", "day", "week" (Monday-aligned), or "month" (1st-of-month). - enforcement"hard" (default, refuse the over-budget call), "soft" (admit but report allowed:false so the caller decides), or "warn" (admit + audit only).

consume(tenant, model, amount) is the single atomic check-and-charge entry point: in "hard" mode it reserves amount only if it fits under the limit, otherwise it refuses without charging. There is no separate "check then add" two-call shape to race against — the reservation and the limit test happen in one operation.

Single-process by default; cross-node via store. The in-memory counter is per-process. Multi-node deployments that need an aggregate ceiling across the cluster supply an opts.store adapter whose reserve (an atomic conditional test-and-charge — "add only if current + amount fits under the limit") and add are atomic on the shared backend: a Redis Lua script, or a SQL UPDATE ... SET used = used + :amt WHERE used + :amt <= :limit RETURNING used. The conditional reserve is what keeps hard enforcement correct under cross-node contention — there is no charge-then-refund window for a concurrent call to observe. The framework records the active cluster node id on every breach event so a denial-of-wallet spike is attributable.

Limit resolution is most-specific-first: perTenantModel[t|m]perTenant[t]perModel[m]limit (the default). Tenant and model identifiers are percent-encoded into the counter key so a hostile tenant name cannot collide with another tenant's budget.

Audit emissions (drop-silent via b.audit.safeEmit): - ai/quota-applied — a consume succeeded. - ai/quota-exceeded — a consume hit the ceiling (refused under "hard"; reported under "soft" / "warn").

NIST AI RMF (AI 100-1) MANAGE 2.x ("AI system performance and trustworthiness are monitored") and EU AI Act Art. 15 (accuracy, robustness and cybersecurity of high-risk systems — resource-exhaustion resilience) map onto this primitive; operators wire its emissions into the same audit chain auditors read.

b.ai.quota.create(opts) #

stable0.12.27soc2gdpr
{
  {
    dimension:        string,    // required, one of:
                                 //   "tokens" | "requests" |
                                 //   "cost-usd" | "compute-hours"
    period:           string,    // required, one of:
                                 //   "second" | "minute" | "hour" |
                                 //   "day" | "week" | "month"
    limit:            number,    // required, default ceiling (> 0)
    perTenant?:       { [tenantId: string]: number },
    perModel?:        { [model: string]: number },
    perTenantModel?:  { [tenantPipeModel: string]: number },
                                 // key is `tenantId + "|" + model`
    enforcement?:     string,    // "hard" (default) | "soft" | "warn"
    store?:           object,    // { reserve, add, get, reset };
                                 // default in-memory (per-process)
    audit?:           boolean,   // default: true
  }
}

Build a per-tenant AI usage-budget enforcer scoped to one dimension and one period. Returns an object exposing consume(tenant, model, amount, opts?) (the atomic check-and-charge), check(tenant, model) (read-only snapshot), snapshot(tenant, model) (alias of check), and reset(tenant?, model?) (drop the current window's counters).

Spin up one enforcer per dimension you meter — e.g. a "cost-usd" monthly budget and a "tokens" per-minute burst cap can coexist as two create() calls sharing the same store.

var budget = b.ai.quota.create({
  dimension:  "cost-usd",
  period:     "month",
  limit:      500,
  perTenant:  { "tenant-vip": 5000 },
  enforcement: "hard",
});
var r = await budget.consume("tenant-acme", "opus-4", 0.42);
// → { tenantId: "tenant-acme", model: "opus-4",
//     dimension: "cost-usd", period: "month", used: 0.42,
//     limit: 500, remaining: 499.58, allowed: true,
//     exceeded: false, windowStart: ..., resetsAt: ... }

Last updated 2026-08-08T16:39:49.652Z by seeder.