Relay docs

Budgets & spend limits

Budgets cap what can be spent, at two levels: one workspace budget sets the ceiling, and each member can hold an allocation out of it. The member allocations may never sum past the workspace ceiling — that invariant is what makes the two levels a budget rather than two independent numbers.

#The two levels

LevelHow manyMeaning
WorkspaceExactly one per workspaceThe ceiling for everything in the workspace.
MemberAt most one per memberThat person's slice of the ceiling.

Both are rows in the same table, distinguished by whether they name a user. Set them in the panel under Budgets → Applies to: The whole workspace or A single member.

The owning workspace is never typed in — it comes from the workspace you have selected (the ?w= in the URL), and the server stamps it on write. A budget filed against a workspace you aren't in is not expressible.

#Rules

Three rules are enforced on every write, and the error tells you which one you hit:

  1. One workspace budget per workspace. A second is rejected — edit the existing one.
  2. One budget per member. Same.
  3. Member allocations never exceed the workspace budget. This applies in both directions: adding or raising a member budget past the free headroom is rejected, and lowering the workspace budget below what is already allocated is rejected too. The second is the one people trip over — the fix is to lower the member budgets first.

Two details worth knowing:

  • Set the workspace budget first. Member budgets are allocated out of it, so there is nothing to allocate from until it exists.
  • Disabled member budgets still count toward the allocated total. If disabling one freed up headroom, re-enabling it could silently push the workspace over its ceiling. Delete it to reclaim the allocation.

The one-per-workspace and one-per-member rules are also filtered unique indexes in the database, so they hold under concurrent writes, not just in the UI.

#Periods and modes

Each budget has a period (daily / weekly / monthly) and a mode:

  • Hard stop — once spend reaches the limit, the gateway rejects further requests with 402 budget_exceeded.
  • Alert only — the limit is tracked and shown, but nothing is blocked.

Spend is not counted per request in SQL. BudgetRefreshService recomputes it from telemetry every Gateway:BudgetRefreshMinutes (default 5), so a hard stop engages within that window rather than instantly — size the cap with that lag in mind, and note that a budget with telemetry unconfigured never advances at all.

#What is enforced at request time

Workspace budgets are enforced. ModelRouter checks them before dispatch, so the 402 costs nothing upstream. The check covers workspace-level and global budgets.

Member budgets are not enforced at request time — they are an allocation and governance control. This is a real limitation and worth being explicit about: the gateway cannot attribute a request to a person. An API key carries a team claim and nothing else, and per-request telemetry has no user column. So a member's spend has nowhere to come from.

Two consequences follow, and the panel shows both rather than hiding them:

  • A member budget's spend reads as "not tracked", not as $0.00 — those are different claims, and a burn bar pinned at 0% would assert the wrong one.
  • Member rows are excluded from the burn cards, and carry an allocation badge instead of a hard-stop / alert-only mode.

What member budgets do give you today is a governed division of the ceiling: an agreed, enforced-on-write split that no one can quietly exceed on paper, and a single place to see how much of the workspace budget is committed versus free.

Closing the gap needs a user dimension on the API key and on the usage events — a schema change, not a wiring change.

#Reading the numbers

The Budgets page shows, for the workspace budget: spend against limit, percentage used, and a projection ("on track — ~72% projected by Mar 31", or the date the limit is expected to be hit). Above the table, an allocation summary reports how much of the ceiling is committed to members and how much is still free.