Overview
Spending limits let you cap estimated USD spend on live AI traffic. In the console they show up as Spending limit (project-wide) and Cost guardrail (per workflow model).
You can set one, the other, or both:
- Project spending limit — total priced spend across the project
- Workflow spend cap — spend on a specific primary, backup 1, or backup 2 model
Each limit uses a UTC period (hourly, daily, weekly, or monthly). When spend hits the cap, new provider calls are blocked and the API returns a budget error.
Different from input guardrails: Input guardrails block unsafe content. Spending limits block requests when a budget threshold is reached.
How checks run
On a normal live request, ModelRiver evaluates limits in this order:
- Test mode — if the workflow is in test mode, all spending limits are skipped
- Cache hit — cached responses with
price = 0skip limits entirely - Project cap — if configured and spend is at or above the cap, the request is blocked immediately (no failover)
- Workflow slot cap — if that model slot is over its cap, it is skipped and the next backup is tried
If the project cap is already reached, backups do not run — even when a workflow slot still shows budget left on Overview.
This applies across sync, async, streaming, playground (production workflows), and OpenAI-compatible routes.
What counts as spend
Project totals
Project spend sums successful request logs where:
statusissuccesspriceis greater than0primary_req_idis empty (top-level requests only — child failover rows are excluded)
Workflow slot totals
Workflow caps track spend for a specific workflow + provider + model pair. Here ModelRiver sums successful logs with a non-null price for that slot, including priced failover attempts on the same model.
Cache hits (price = 0) never add to either total and never trigger a budget check.
Budget periods
All periods use UTC boundaries:
| Period | Resets at |
|---|---|
hourly | Top of each UTC hour |
daily | Midnight UTC |
weekly | Monday 00:00 UTC |
monthly | First day of the UTC month |
Overview and budget error responses include period_start and reset_at when helpful.
Set a project spending limit
- Open the project and go to Settings (sidebar)
- In Spending limit, enter Maximum spend (USD) — amounts like
$0.009are supported (up to three decimal places) - Pick Reset every (
hourly,daily,weekly, ormonthly) - Save
Clear the amount and save to remove the limit. The amount must be greater than zero, and a period is required whenever a cap is set.
Set workflow spend caps
- Open Workflows and edit a production workflow
- On the primary, backup 1, or backup 2 step, open Cost guardrail
- Set Budget (USD) and Reset
- Save the workflow
Only slots with a provider and model selected can be capped.
When a capped slot is over budget, that model is skipped. ModelRiver moves on to the next backup if one exists. If every tried model is skipped for budget reasons, the request fails with workflow_budget_exceeded.
Overview page
The Spending limits section on Overview shows:
- Project card — spent vs cap, remaining budget, reset time, and a config warning when any production workflow model is missing USD catalog pricing
- Per-workflow rows — spend and cap for each capped slot, with quick edit controls
- Summary chips — protected workflows, models running low (80%+), and models at limit
Bars turn amber around 80% utilization and red at the cap. A project can show a config warning even when spend is still low, if pricing is missing for routable models.
Soft enforcement
Spend totals are cached for about 10 seconds to keep checks fast. Under concurrency, a few extra requests can slip through before the next block — you may see spent slightly above cap in Overview or error payloads (for example $0.011797 against a $0.011 cap).
The cap value itself always comes from your saved settings. Blocks happen when cached spend is already >= cap, not based on a forecast of the current request.
Pricing must be known
Caps only work when ModelRiver has USD pricing for the model being routed.
| Case | Workflow cap | Project cap |
|---|---|---|
| USD pricing in catalog | Normal enforcement | Normal enforcement |
| Pricing unknown | Slot skipped; terminal workflow_budget_config_error if nothing else can run | Hard block with project_budget_config_error |
Overview shows a config warning when any active production workflow model lacks pricing. Fix catalog pricing or remove the cap until it is available.
When a limit blocks a request
Workflow cap — workflow_budget_exceeded (402)
All models attempted in the failover chain were skipped for budget. The response includes an attempts array with reasons like daily budget ($0.009) reached.
In Request Logs you will usually see:
- One or more Skipped rows (
response_source: budget_guardrail) - A parent Error row with the terminal API error payload
Project cap — project_budget_exceeded (402)
Spend hit the project cap before routing. No backups are tried. The response includes cap_usd, spent_usd, period, and reset_at.
Request Logs show a single Error row with response_source: budget_guardrail, zero tokens, and no provider call.
See Error handling for response examples and legacy error aliases (budget_exceeded, budget_config_error).
Test mode and Playground
| Traffic | Limits enforced? |
|---|---|
| Workflow in test mode | No |
| Playground + production workflow | Yes — counts as live spend |
| Playground + test-mode workflow | No |
Use test mode when you want to exercise integrations without touching budgets.
Practical tips
- Put caps on individual models first when you care about per-feature spend; add a project cap as a backstop
- Use hourly or daily periods while tuning values, then move to weekly or monthly in production
- After saving caps, run a few live requests and confirm Overview numbers move as expected
- Use cost analytics to pick realistic cap values from actual log prices
Next steps
- Cost analytics — read spend from Request Logs
- Error handling — budget error types and HTTP codes
- Build a workflow — models, backups, and optional caps
- Console — settings and Overview
- Back to Observability