Skip to main content

Spend Controls

Two independent caps gate new deployments at the provisioning scheduler. Throttle compares the live $/hr burn rate (catalog $/hr summed across every running VM, plus the candidate's $/hr) against its cap. Budget compares calendar-window spend (settled cost + catalog estimates for VMs whose billing hasn't landed) against its cap. Neither kills running jobs.

PrimitiveHorizonCatchesClears
ThrottleInstantaneousConcurrent fleet $/hrWhen VMs end
BudgetCalendarSustained driftDay / week / month

Use them together: throttle caps how much you can be burning at once; budget caps total exposure across a calendar period.

How it works

When a deployment is queued, the scheduler checks every active cap before dispatching. If any cap is at or over its limit, the deployment stays Queued with a "blocked by …" reason visible in anycloud status and anycloud list. Once the cap clears — running VMs finish (throttle), the calendar rolls over (budget), or you raise the cap — the next scheduler tick dispatches it automatically.

Running jobs are never killed by a cap. Throttle and budget only gate the queued → provisioning transition.

When a cap blocks

anycloud submit always accepts — the deployment id comes back immediately. The cap is enforced later, at the dispatch step. A blocked deployment stays Queued with a blocked by … message in anycloud status and anycloud list:

  • Throttle: blocked by throttle: rate $X/hr ≥ cap $Y/hr
  • Budget: blocked by daily|weekly|monthly budget: spent $X / $Y — resumes YYYY-MM-DD HH:MM UTC

Budget messages name the next UTC reset; throttle clears whenever running VMs end, so there's no fixed time to show.

Nothing else fires — no email, Slack, or webhook. The deployment waits indefinitely; the scheduler re-checks every few seconds and dispatches as soon as the cap clears. Cancel with anycloud cancel <id> if you don't want to wait.

Throttle

Burn-rate cap ($/hr). Blocks new dispatches when the live fleet's $/hr (running VMs + candidate) is at or over the cap. The moment running VMs end, the burn rate drops — no trailing-window ghost.

anycloud throttle set 20                  # account-wide: $20/hr
anycloud throttle set 5 --agent-session # each agent session: $5/hr
anycloud throttle show
anycloud throttle unset
anycloud throttle unset --agent-session

Two caps coexist: account-wide (default) and per agent-session.

Budget

Calendar-window cap. Blocks new dispatches when window-to-date spend is at or over the cap.

anycloud budget set 100 --per day
anycloud budget set 500 --per week
anycloud budget set 2000 --per month
anycloud budget set 50 --per day --agent-session
anycloud budget show
anycloud budget unset --per day

Windows reset at UTC boundaries:

  • day — 00:00 UTC
  • week — Monday 00:00 UTC
  • month — 1st of month, 00:00 UTC

Up to six budgets coexist (three windows × two scopes). When multiple budgets are active, the lowest binds — anycloud budget show names which one is closest to its cap.

Scopes

  • account (default) — counts every deployment, including interactive anycloud submit from a human shell.
  • agent-session — counts only deployments from one specific agent run (Claude Code, Cursor, Codex, Aider). Each session has its own counter. Interactive submits have no session, so they're not bound by agent-session caps — pair with an account-wide cap if you want to bound humans too.

Auto-detection of agent sessions lives in the CLI (see the job-lifecycle attribution column). A session that doesn't auto-detect won't count against agent-session caps.

What each cap measures

  • Throttle sums the catalog $/hr of every VM currently running. No window, no proration. The candidate's $/hr is added to that sum before the comparison, so a burst within one scheduler tick can't all dispatch on the same pre-burst snapshot.

  • Budget sums per-VM cost over the calendar window from two sources:

    • actual — settled cost from the cloud's billing API, prorated by the window intersection. Lands ~24h after a VM terminates.
    • estimated — catalog $/hr × elapsed_within_window for VMs whose actual cost hasn't settled.

    anycloud budget show prints both so you can see how much of the total is still pending billing-API reconciliation.

Design notes

  • Throttle pre-charges the candidate. Each candidate's $/hr is added to the live burn rate before the comparison, so a burst submitted on the same scheduler tick can't all dispatch on the same pre-burst snapshot. Falls back to reactive (no pre-charge) when the catalog can't price the candidate.
  • Budget is reactive. Calendar windows are large enough that a tick's worth of overshoot is negligible.
  • Single chokepoint. Both caps gate at the provisioning scheduler — the only path from "queued" to a real VM. anycloud submit always accepts; if a cap is at its limit, the deployment stays Queued instead.
  • Polling, not events. Each tick (a few seconds) re-evaluates every queued row. No event subscriptions or callbacks needed.

What's not included (yet)

  • Threshold alerts (50/75/90/100%) — hard caps only.
  • Forecasting.
  • Webhooks on threshold.
  • Pause / kill of running jobs.
  • Scopes beyond agent-session (no per-cred, per-region, per-agent-name).
  • Per-job duration estimates / --max-duration requirement.