Browse docs
--- title: "Budgets" description: "Set spend limits per user path and enforce them through workflow budget controls." icon: "wallet" keywords: ["budgets", "spend limits", "cost controls", "user path"] ---
Overview
Budgets let you set spend limits for a tenant-scoped user_path subtree. Aurora evaluates them from tracked usage cost records and blocks matching requests when a limit has already been spent.
Use budgets when you want limits such as:
/team/alphacan spend$10per day/team/alphacan spend$50per week/has a global monthly limit
Enable budgets
Budgets are Enterprise-gated. Enable them in an Enterprise profile:
USAGE_ENABLED=true
BUDGETS_ENABLED=trueBudgets depend on usage tracking because spend is calculated from usage cost records.
If usage tracking is disabled, Aurora starts with budget management disabled and logs a warning.
Create budgets
You can create budgets in the dashboard:
Budgets -> Create BudgetDashboard-created budgets are marked as manual. Budgets loaded from YAML or environment variables are marked as config.
You can also seed budgets from YAML:
budgets:
enabled: true
user_paths:
- path: "/team/alpha"
limits:
- period: "daily"
amount: 10.00
- period: "weekly"
amount: 50.00
- path: "/"
limits:
- period: "monthly"
amount: 500.00Or use environment variables:
SET_BUDGET_TEAM__ALPHA="daily=10,weekly=50"
SET_BUDGET_="monthly=500"The suffix after SET_BUDGET_ becomes a user path. Use double underscores (__) between path segments; single underscores remain part of a segment:
SET_BUDGET_TEAM__ALPHA->/team/alphaSET_BUDGET_USER_123->/user_123SET_BUDGET_->/
There is no escape for a literal double underscore inside a path segment. Use YAML or the dashboard for paths that need a __ segment value.
Supported standard periods are:
The Seconds column is the internal period identifier. Standard periods use the configured reset-anchor logic; for example, monthly is stored as 2592000 but resets on calendar month anchors and clamps the reset day to shorter months. Only custom period_seconds values behave as fixed-second windows.
For custom windows, set period_seconds in YAML:
budgets:
user_paths:
- path: "/team/alpha"
limits:
- period_seconds: 7200
amount: 5.00How matching works
Budget paths apply to the configured path and its descendants:
- budget path
/team - request path
/team/app - result: budget applies
Sibling paths do not match:
- budget path
/team - request path
/team-alpha - result: budget does not apply
If multiple budgets match a request, Aurora checks all matching limits. The request is rejected if any matching limit is exhausted.
Workflow enforcement
The active workflow controls whether budget checks run for a request.
In a workflow payload:
{
"schema_version": 1,
"features": {
"budget": true,
"cache": true,
"audit": true,
"usage": true,
"guardrails": true,
"fallback": true
}
}Use scoped workflows to turn budget enforcement on or off for a provider, model, or user_path subtree. See Workflows for matching precedence.
Reset windows
Budget reset anchors are configured in the dashboard under:
Settings -> Budget ResetsThe reset settings are evaluated in UTC.
For monthly budgets, if the configured day does not exist in a month, the reset runs on the last day of that month. For example, a monthly reset day of 31 runs on April 30 and on February 28 or 29.
Editing a budget changes the limit but does not reset the current period. Use the row-level Reset action to start a new period for one budget, or Settings -> Reset All Budgets to reset all budgets.
Admin API
Budget management is also available through the admin API:
curl -H "Authorization: Bearer $AURORA_MASTER_KEY" \
http://your-aurora-host/admin/api/v1/budgetsBudget calls are tenant-scoped. Without tenant_id, the request uses the authenticated request context tenant, which is default for master-key/OSS flows. Passing tenant_id selects a specific tenant for master-key callers; identity-session callers can only operate on their authenticated tenant.
List one tenant's budgets:
curl -H "Authorization: Bearer $AURORA_MASTER_KEY" \
"http://your-aurora-host/admin/api/v1/budgets?tenant_id=acme"Create or update a budget:
curl -X PUT http://your-aurora-host/admin/api/v1/budgets/%2Fteam%2Falpha/daily \
-H "Authorization: Bearer $AURORA_MASTER_KEY" \
-H "Content-Type: application/json" \
-d '{
"tenant_id": "acme",
"amount": 10.00
}'Delete a budget:
curl -X DELETE "http://your-aurora-host/admin/api/v1/budgets/%2Fteam%2Falpha/daily?tenant_id=acme" \
-H "Authorization: Bearer $AURORA_MASTER_KEY"The dashboard tenant selector's empty option means Default tenant, not all tenants. True all-tenant budget listing is intentionally not enabled by default; add a separately gated superadmin endpoint if your deployment needs that view.
Reservations and multi-instance enforcement
If a request includes X-Aurora-Estimated-Cost, Aurora creates an in-flight budget reservation before forwarding the request. The reservation is included in budget checks until it is reconciled by the usage logger with the request's actual total_cost, explicitly released, or expires after ten minutes.
SQLite and PostgreSQL budget stores persist reservations in budget_reservations, so replicas sharing the same store see each other's in-flight estimated spend. Stores that do not implement reservation persistence fall back to in-process reservations.
For strict hard caps across high-concurrency PostgreSQL replicas, pair this with a deployment-level concurrency strategy or database serialization around reserve and check. The persisted reservation table prevents invisible cross-replica spend, but simultaneous reserve/check operations can still race if they are not serialized by the deployment.
See Admin Endpoints for the endpoint list.