Add a spend cap
Bound how much a plan's metered usage can cost — by funding it and blocking at zero.
Outcome
A plan has an explicit spend ceiling: metered usage draws down a fixed amount of value and the gateway denies further billable work at zero. Use this to limit a subscriber's — and your — exposure on metered plans.
Prerequisites
- A meter and pricing catalog the plan binds
- A chosen ceiling in dollars
- Approval for a billing change
Change the plan
A spend cap in the new model is funding plus a block policy. Prepay (or
include) exactly the value the subscriber may spend and set
fs.exhaustion.block; the gateway reserves each request's economic maximum
against that value before forwarding it, so the cap holds before the origin is
called rather than after the invoice.
For a subscription that includes a fixed monthly usage budget and must stop
there, use custom (an included bucket with block is not a hybrid shape,
which requires overage):
fs.plan("pro-capped", {
kind: fs.plan.kind.custom,
price: fs.money.usd(49).monthly(),
usagePricing: tokenPricing.current(),
funding: { buckets: [fs.included(fs.money.usd(200))] },
spendPolicy: { onExhaustion: fs.exhaustion.block },
grants: [chat],
limits: [requests.perMinute(600)],
});
For a wallet the subscriber funds themselves, use prepaid with topUp: true
— the cap is whatever they have paid for. Every route the plan can spend on
must declare a bound (maxOutputUnits, chunkPolicy, or a post-stream
settlementMax) so the reservation is finite; the compiler rejects an unbounded
one.
Validate and test on preview:
farthershore build --format json
git push -u origin HEAD:env/spend-cap-preview
farthershore business show acme --env spend-cap-preview --format json
Verify
Confirm the preview contract's pro-capped plan is kind: "custom" with a
$200 included bucket and block exhaustion. Exercise usage near the cap with a
preview subscriber: the bill preview's allowance remainingNanos falls with
each request, and the first request that cannot be covered is denied
credit_exhausted (402) before it reaches your origin.
Common failures
- Build fails with
PLAN_KIND_CONTROL_MISMATCH:hybridrequiresexhaustion.overage; a blocking allowance iscustomorprepaid. - Build fails with
ADMISSION_OUTPUT_BOUND_REQUIRED: a route the plan can spend on has an unbounded measure — addmaxOutputUnits. - Usage continues past the cap: the plan is
overage, notblock; read the release'sspendPolicy. - Plan list is unchanged: the preview build may not have applied yet.
Recover
Revert the preview commit. If released, the new bucket amount applies to new issuances; existing subscribers keep their current-period bucket. Prepare and approve a forward correction.
Next steps
See billing strategies, funding & allowances, monetary admission, and plans.
Agent prompt
Give the metered
proplan a $200 monthly spend cap: a kind-custom plan with a $200 included bucket and exhaustion.block, every spend route bounded with maxOutputUnits. Validate in preview, prove the credit_exhausted denial, and require approval before release.