Foreshock

Operate

Budget exhaustion

Screening spend is bounded on purpose, running out produces a hold rather than a shortcut, and the dangerous remedy is the automatic one.

Updated
2026-08-24

Layer B — third-party attribution vendors — is billed per call. The budget exists so that a traffic spike, a retry storm, or a misconfigured loop cannot produce an unbounded bill. It is a cost control, and like every other control in this system, its degraded path is HOLD.

What you see

On the decision endpoint: HTTP 200, verdict: HOLD, reason code BUDGET_EXHAUSTED.

Not a 402, not a 429, not an error. A budget that has run out is a fact about your account, and the decision it produces is a real decision with a real decision_id and a real evidence reference.

Watching the spend

billable_units is returned on both POST /v1/screen/address and POST /v1/decide/deposit.

  • Layer A is never billed. A layer-A-only screening response is 0.
  • An idempotent replay is not billed again. It carries Idempotency-Replayed: true.
  • Requesting depth: B does not guarantee a vendor call is made — your routing rules, cost gate, and cache all sit in front of it. When no vendor call happened, layer_b is null.

Alert on the burn rate, not on the exhaustion. By the time you see BUDGET_EXHAUSTED, holds are already accumulating.

Recovering

Two ways out, and they are not equivalent.

Wait for the period to roll. Correct, and free. Deposits held on BUDGET_EXHAUSTED carry RE_DECIDE_AFTER_RECOVERY in required_actions — re-decide with a new idempotency key once the budget is available.

Raise the budget. Also correct, when a human decides that the new level is the right one. Make it a decision with a name attached, not an automatic response to a threshold.

The automatic top-up is the dangerous one

An automatic budget increase triggered by BUDGET_EXHAUSTED removes the only backstop against a runaway loop. The condition that exhausted the budget is usually not “business grew 40% overnight”; it is a retry loop with a fresh idempotency key per attempt, a shadow-mode deployment left running at full rate, or a backfill someone started and forgot.

Before raising anything, check three things:

  1. Is billable_units per deposit what you expected, or is one deposit producing several decisions?
  2. Are your idempotency keys stable per deposit, or fresh per attempt?
  3. Is anything screening at depth: B that only needs layer A?

Most budget incidents are one of those three, and none of them is solved by more budget.