:::info Executable tutorial
This page is generated from a tested Jupyter notebook. Open it in Google Colab or view the source notebook.
:::
Enforce quotas and spend caps
Per-request pricing does not limit cumulative usage. This tutorial configures a daily output-token quota, observes alert thresholds, verifies that reservations count toward the limit, and confirms that an over-limit request is rejected atomically.
Learning objectives
After completing this tutorial, you can:
- Read quota state for an account and plan
- Interpret alert and block thresholds
- Account for active reservations in quota usage
- Verify that rejected work does not change the balance
Prerequisites
- Complete the plans and allowances tutorial
- Start the notebook server from
samples/python/notebooks/
Setup
Same sandbox: a temporary Postgres store with the standard config. USER_ADA is put on pro and loaded with 200 credits. Metered deductions below the cap are cheap, so most of the action happens in quota state, not the wallet.
from decimal import Decimal
from bursar.metrics import UsageMetrics
from shared import cleanup, base_config, publish_config, start_postgres_store, USER_ADA
def completion(output=Decimal(500)):
return UsageMetrics(
operation="completion",
measures={
"input_tokens": Decimal(1000),
"output_tokens": output,
"cache_read_tokens": Decimal(200),
},
dimensions={"model": "gpt-4o"},
)
store, pgdata = start_postgres_store()
bursar = publish_config(store, base_config())
bursar.accounts.on_account_created(USER_ADA, "signup")
bursar.credits.set_user_plan(USER_ADA, "pro")
bursar.credits.add_credits(USER_ADA, Decimal("200.00"), entry_type="purchase", idempotency_key="topup")
print("ready")
Reading the quota state
The pro plan defines one quota: daily_tokens, 500,000 output_tokens per calendar day, enforced with block. emit_at_percent lists the alert thresholds (80% and 100%).
Known issue: the SDK's typed get_quota_state currently crashes with a pydantic ValidationError (the RPC returns a datetime where the model expects a string), so this notebook reads the raw RPC through the store and constructs QuotaState by hand. The shape is exactly what the typed call would return.
from bursar.credits.types import QuotaState
def quota_state(user_id=USER_ADA):
try:
return bursar.credits.get_quota_state(user_id)
except Exception as exc:
print("typed get_quota_state:", type(exc).__name__, "- using raw RPC")
rows = store._callproc("get_subject_quota_state", [user_id, None])
return [
QuotaState(
user_id=r["user_id"],
quota_key=r["quota_key"],
operation=r["operation_key"],
measure=r["measure_key"],
limit=Decimal(r["quota_limit"]),
consumed=Decimal(r["consumed"]),
reserved=Decimal(r["reserved"]),
remaining=Decimal(r["remaining"]),
overage=Decimal(r["overage"]),
enforcement=r["enforcement"],
window_start=r["window_start"].isoformat(),
window_end=r["window_end"].isoformat(),
emit_at_percent=[float(p) for p in r["emit_at_percent"]],
)
for r in rows
]
q = quota_state()[0]
print(f"quota_key={q.quota_key} operation={q.operation} measure={q.measure}")
print(f"limit={q.limit} consumed={q.consumed} remaining={q.remaining}")
print(f"enforcement={q.enforcement} emit_at_percent={q.emit_at_percent}")
print(f"window: {q.window_start} -> {q.window_end}")
Reservations count too
Admission checks the quota before work starts: two 200,000-token holds fit (400,000 ≤ 500,000), the third would cross 600,000 and is refused. Held tokens appear in quota_state.reserved; releasing returns them. The refused attempt is itself recorded as a blocked quota event (the event list below will show it alongside the later threshold event).
from bursar.credits.service_types import ReserveOptions
held = []
for i in range(3):
try:
lease = bursar.credits.reserve(
USER_ADA,
completion(output=Decimal("200000")),
ReserveOptions(ttl=60, idempotency_key=f"quota:reserve:{i}"),
)
held.append(lease)
print(f"reserve {i + 1}: ok hold={lease.amount} available={lease.available}")
except Exception as exc:
print(f"reserve {i + 1}: {type(exc).__name__} (RPC refused: would exceed quota)")
q = quota_state()[0]
print(f"quota after holds: consumed={q.consumed} reserved={q.reserved} remaining={q.remaining}")
for lease in held:
bursar.credits.release(USER_ADA, lease.lease_id)
q = quota_state()[0]
print(f"quota after release: reserved={q.reserved} remaining={q.remaining}")
Streaming up to the cap
Eleven metered completions stream 420,000 output tokens in 40,000-token steps. At 80% (400,000) the quota emits a threshold event carrying the idempotency key of the charge that crossed the line.
total = Decimal(0)
while total < Decimal("420000"):
step = min(Decimal("40000"), Decimal("420000") - total)
bursar.credits.deduct(USER_ADA, completion(output=step), idempotency_key=f"stream-{int(total)}")
total += step
if int(total) % 200000 == 0:
q = quota_state()[0]
print(f"consumed={q.consumed} remaining={q.remaining}")
for e in bursar.credits.list_quota_events(USER_ADA):
print(f"event: type={e.event_type} threshold={e.threshold_percent} key={e.idempotency_key}")
Hitting the wall
A single 600,000-token request is blocked outright: QuotaExceededError with code QUOTA_EXCEEDED, nothing is charged, and the quota records a blocked event. The counter stays at 420,000 — overage is refused, not accumulated.
balance_before = bursar.credits.get_balance(USER_ADA).balance
try:
bursar.credits.deduct(USER_ADA, completion(output=Decimal("600000")), idempotency_key="big-run")
except Exception as exc:
print("blocked:", type(exc).__name__, getattr(exc, "code", None))
print("balance unchanged:", bursar.credits.get_balance(USER_ADA).balance == balance_before)
q = quota_state()[0]
print(f"consumed={q.consumed} remaining={q.remaining}")
for e in bursar.credits.list_quota_events(USER_ADA):
print(f"event: type={e.event_type} threshold={e.threshold_percent} key={e.idempotency_key}")
Windows and plan differences
The daily window rolls at midnight UTC; window_start / window_end mark the current one. Quotas are defined per plan: the free plan has no quota rows at all, so a free account reads an empty list.
q = quota_state(USER_ADA)[0]
print("current window:", q.window_start, "->", q.window_end)
from shared import USER_ALEX
bursar.accounts.on_account_created(USER_ALEX, "signup")
print("free-plan quota rows:", quota_state(USER_ALEX))