Org Daily Cost
Technical reference. This page is for integrations, advanced configuration, or platform operations. For portal tasks, start with the user guide.
The org daily-cost pool tracks every LLM call’s reserved spend against a per-organization, UTC-day calendar bucket. It implements a two-phase commit lifecycle: the runtime-gateway acquires a reservation BEFORE the provider call (so an over-budget call is rejected before any spend), then commits the actual prompt + completion tokens AFTER the call completes. Pricing is frozen into the reservation row at acquire time, so the commit math cannot drift if pricing changes mid-flight.
The pool was added in ADR 0063 alongside the provider TPM pool. Unlike TPM (which fails open on Redis), the cost pool fails closed — Redis atomicity is required for the reservation snapshot, and a Redis outage rejects new reservations rather than silently overspending.
What this surface does
Every LLM call passes through multi_pool_acquire in the runtime-gateway, which acquires a cost reservation AFTER the TPM acquire. The reservation amount is bounded:
cents_reserved = ceil((prompt_tokens × input_cpm + max_completion_tokens × output_cpm) / 1_000_000)max_completion_tokens is either pinned by the caller or defaults to ORQESTRA_DEFAULT_MAX_COMPLETION_TOKENS (default 2000). The pricing snapshot is copied into the reservation row at acquire time so a mid-flight pricing supersede cannot retroactively move the reservation.
The reservation is in state RESERVED until the LLM call completes. On success the runtime-gateway commits the actual prompt + completion token totals; the commit caps the total at cents_reserved + slack (ORQESTRA_COST_OVER_COMMIT_SLACK_CENTS, default 0) and surfaces residual via v1.governance.cost_over_commit_detected. The state transitions RESERVED → COMMITTED. On provider error the runtime-gateway releases the reservation; the state transitions RESERVED → RELEASED and the daily counter is refunded. On EgressBlockedError (the runtime-gateway’s safety filter rejecting a response that already cost real money), the runtime-gateway commits from exc.usage so the operator pays for what the provider charged.
A stuck RESERVED row past grace_seconds (default 600s) is detected by the cost-reaper Celery beat job (orqestra.governance.cost_reaper_tick, every 600s) and triggers operator alerts — see the Cost & Pricing Recovery Runbook .
Admin routes
Eight admin routes live under /v1/governance/organizations/{org_id}/... and are gated by Permission.GOVERNANCE_POOL_VIEW (reads) or Permission.GOVERNANCE_POOL_MANAGE (writes), both at organization scope.
| Method | Path | Permission | Purpose |
|---|---|---|---|
GET | .../daily-cost-config | GOVERNANCE_POOL_VIEW | Read active limits + override + circuit-break for the org. |
PUT | .../daily-cost-config | GOVERNANCE_POOL_MANAGE | Set durable daily-cost limits. Supersedes any prior limits row. |
POST | .../daily-cost-override | GOVERNANCE_POOL_MANAGE | Apply a cap-lift override (≤ 24h TTL). |
DELETE | .../daily-cost-override/{override_id} | GOVERNANCE_POOL_MANAGE | Revoke an active override. |
POST | .../daily-cost-circuit-break | GOVERNANCE_POOL_MANAGE | Trigger an org-wide LLM stop (≤ 30d auto-clear). |
DELETE | .../daily-cost-circuit-break | GOVERNANCE_POOL_MANAGE | Clear an active circuit-break. |
POST | .../daily-cost-reservations/reset | GOVERNANCE_POOL_MANAGE | Reset the daily counter and per-reservation keys. Reason-required, audited. |
GET | .../daily-cost-usage | GOVERNANCE_POOL_VIEW | Read live cents_used_today from the Redis counter. |
Three internal routes (POST /v1/governance/cost/acquire, POST /v1/governance/cost/commit, DELETE /v1/governance/cost/reservations/{request_id}) are consumed only by the runtime-gateway and require an internal service / system / workload actor.
Request / response shapes
PUT daily-cost-config
{
"daily_budget_cents": 10000,
"max_completion_tokens_default": 2000,
"alert_threshold_pct": 80
}POST daily-cost-override
{
"cents_ceiling": 50000,
"reason": "release-2026-04-27: bulk re-evaluation against new policy bundle",
"expires_at": "2026-04-27T22:00:00Z"
}expires_at more than 24h in the future returns 400 override_ttl_too_long.
POST daily-cost-circuit-break
{
"reason": "incident-2026-04-27: investigate admission at the configured daily cost limit",
"auto_clear_at": "2026-04-28T02:00:00Z"
}auto_clear_at more than 30 days in the future returns 400 circuit_break_ttl_too_long.
GET daily-cost-usage returns the live counter:
{
"organization_id": "8c3a1b9e-0cae-4a63-8ad8-50ee3d5e60f1",
"date_utc": "2026-04-27",
"cents_used_today": 7340
}Internal POST cost/commit returns the commit outcome including replay flag:
{
"cents_committed": 132,
"cents_released": 18,
"cents_used_today_after_commit": 7472,
"replay": false
}cents_used_today_after_commit is an advisory running total. It can be null
when the spend was committed but the post-commit Redis counter read was
unavailable; treat that as unknown, not as zero. A retry of the same request_id
returns the cached outcome with replay: true and does not double-count.
Example invocations
# Read the active config (limits + override + circuit-break)
curl -H "Authorization: Bearer $TOKEN" \
"https://control-plane/v1/governance/organizations/$ORG_ID/daily-cost-config"# Set the daily budget to $100 and the default max_completion_tokens to 2000
curl -X PUT \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"daily_budget_cents": 10000, "max_completion_tokens_default": 2000, "alert_threshold_pct": 80}' \
"https://control-plane/v1/governance/organizations/$ORG_ID/daily-cost-config"# Trigger an org-wide circuit-break for 4 hours
curl -X POST \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d "{\"reason\": \"incident-2026-04-27\", \"auto_clear_at\": \"$(date -u -d '+4 hours' +%Y-%m-%dT%H:%M:%SZ)\"}" \
"https://control-plane/v1/governance/organizations/$ORG_ID/daily-cost-circuit-break"# Read live cents-used today
curl -H "Authorization: Bearer $TOKEN" \
"https://control-plane/v1/governance/organizations/$ORG_ID/daily-cost-usage"# Reset the daily counter (incident-only — refunds the budget)
curl -X POST \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"reason": "incident-2026-04-27: rg-pod-3 oom-killed before commit; provider not charged per access logs"}' \
"https://control-plane/v1/governance/organizations/$ORG_ID/daily-cost-reservations/reset"The same operations are wrapped by the CLI: orqestractl pool cost get, orqestractl pool cost set, orqestractl pool cost override, orqestractl pool cost break, orqestractl pool cost clear, orqestractl pool cost reset, orqestractl pool cost usage.
Defaults and configuration
Fallback values used only when no active daily-cost limits row exists for the org:
| Variable | Default | Purpose |
|---|---|---|
ORQESTRA_DEFAULT_ORG_DAILY_COST_CENTS | 10000 | Fallback daily_budget_cents. |
ORQESTRA_DEFAULT_MAX_COMPLETION_TOKENS | 2000 | Fallback max_completion_tokens injected into the cost-acquire upper-bound. |
ORQESTRA_DAILY_COST_SNAPSHOT_HOUR_UTC | 0 | UTC hour at which the daily snapshot job runs (Celery beat fires at <hour>:05). |
ORQESTRA_COST_REAPER_INTERVAL_SECONDS | 600 | Cost-reaper SCAN interval. |
ORQESTRA_COST_REAPER_GRACE_SECONDS | 600 | Grace window before a RESERVED row is treated as stuck. |
ORQESTRA_COST_REAPER_DLQ_HOURS | 96 | Dead-letter window — past this age the reaper emits the page-out event. |
ORQESTRA_COST_OVER_COMMIT_SLACK_CENTS | 0 | Slack added to the reservation cap on commit so float-rounding from providers doesn’t reject in-budget calls. |
ORQESTRA_COMMIT_RETRY_ATTEMPTS (RG-side) | 3 | Cost-commit retry attempts (backoff 2s/10s/30s). On exhaustion the reaper takes over. |
Operator alerts
The cost pool has four Prometheus alerts (deploy/prometheus/alerts/cost-governance.yml) for reservation recovery and snapshot freshness. It has no statistical usage-anomaly score or alert; the configured absolute daily cost limit remains the admission control.
| Alert | Severity | Trigger | Operator action |
|---|---|---|---|
CostCommitStuck | warning | cost_stuck_reservations_count > 5 for 10 min | See runbook Shape 1 : triage stuck rows via daily_cost_snapshot.late_commit_count. |
CostCommitStuckOldestAge | warning | cost_stuck_reservations_oldest_age_seconds > 3600 (1h) | Same as above; the older the row, the more likely the runtime-gateway crashed mid-commit. |
CostCommitDeadLetter | page-out | DLQ-window crossing | A reservation has waited longer than ORQESTRA_COST_REAPER_DLQ_HOURS (default 96h) without committing or releasing. Operator must decide release vs wait based on provider access logs. |
CostSnapshotMissed | warning | cost_snapshot_heartbeat_seconds > 5400 (90 min) | See runbook Shape 4 : check Celery beat, manually rerun the tick (UPSERT-idempotent). |
The four alerts are operator-actionable and have procedures in the recovery runbook. The metrics they consume are exported on the worker-owned metrics endpoint:
cost_acquires_total{outcome}— counter, every acquire attempt with the resolved outcome (allowed,budget_exceeded,circuit_broken,override_allowed,pricing_unavailable, etc.).cost_commits_total{outcome, replay}— counter, every commit attempt.cost_used_cents{org_id}— gauge sampled from the Redis daily counter.cost_snapshot_heartbeat_seconds— gauge, seconds since the snapshot job last completed.cost_stuck_reservations_count— gauge, count of RESERVED rows pastgrace_seconds.cost_stuck_reservations_oldest_age_seconds— gauge, age of the oldest stuck row.
Related
- Provider TPM Pools — the throttle-side companion to org daily cost; TPM is acquired BEFORE cost in the multi-pool wrap.
- Pricing Table — the platform-scoped (provider, model) pricing rows whose snapshot is frozen into every cost reservation.
- Cost & Pricing Recovery Runbook — operator runbook for stuck reservations, pricing audits, anomaly investigation, and snapshot reruns.
- ADR 0063 — Provider TPM and organization daily cost pools .