Monetary admission
How the gateway bounds each request's spend before forwarding it — admission descriptors, clamps, chunked streaming, and the deny codes.
How the gateway bounds each request's spend before forwarding it — admission descriptors, clamps, chunked streaming, and the deny codes.
The gateway does no pricing. For plans that can run out of money (prepaid,
hybrid while an included or prepaid bucket is paying, custom with block,
rail.x402), core compiles an admission descriptor per route into the
commercial release. The descriptor is a per-category linear bound the gateway
evaluates with integer arithmetic; the result is the request's economic
maximum, reserved against the subscriber's available funding before the request
is forwarded.
economicMaximumNanos = max( perOpFloor, Σ categoryBound_i × maxNanosPerUnit_i )
Coefficients are opaque compiler outputs derived from the rating context with
ceiling rounding; rating uses floor. So final charge ≤ admitted maximum holds by construction, and a "20x cache-heavy" workload is not
over-reserved: each token category has its own bound.
| Bound source | Example | Authored with |
|---|---|---|
exact | request count = 1; gateway-tokenized uncached input | nothing — the gateway knows it |
request_declared | the client's max_tokens after clamping | fs.meterRoutes(..., { maxOutputUnits: out.atMost(8192) }) |
route_cap | max batch items; a post-stream settlement maximum | caps: [measure.atMost(n)], postStream: { settlementMax } |
For prepaid-class plans every chargeable measure on the route must have a
finite bound. The compiler rejects an unbounded output measure
(ADMISSION_OUTPUT_BOUND_REQUIRED), a client knob that could raise a bound but
is not clamped (ADMISSION_UNBOUNDED_KNOB_UNCLAMPED), and prepaid post-stream
without a settlement max (PREPAID_POST_STREAM_SETTLEMENT_MAX_REQUIRED).
maxOutputUnits: out.atMost(8192) does two things: it bounds the admission
category, and it makes the gateway rewrite the request — max_tokens /
max_output_tokens and their protocol aliases are parsed as a non-negative
integer, clamped down to the bound, and set to the bound when missing, all
before the request is signed upstream. Billing truncation and product
truncation are therefore the same event. A malformed or conflicting knob is
422 invalid_admission_knob; a knob above the bound that cannot be safely
rewritten is 422 admission_bound_exceeded. Neither reaches the upstream.
maxOutputUnits; the whole operation is reserved
up front.chunkPolicy: { bound: out.atMost(65536), chunkUnits: 1024 };
the gateway reserves chunkUnits at a time up to the cumulative
per-operation ceiling. When a top-up cannot be reserved, the stream stops at
the preceding admitted chunk boundary; the final charge never exceeds the sum
of admitted chunks. Exclusive with maxOutputUnits.postStream: { settlementMax: [measure.atMost(n)] } so admission can reserve a finite maximum.An actual measurement above its admitted bound is an invariant breach: core
rates what it can, opens a settlement hold (admission_bound_breached), and
alerts. It never silently over-debits.
The reservation is a first-class strategy in the gateway's usage meter — the
same lease/spend/release/checkpoint algebra as structural rate limits, with
nanodollars as its unit — riding the same Durable Object call as every other
constraint. Reap releases reserved − spent. It replaces the retired credit
mirror: exact algebra against the ledger-derived funding projection instead of
a mirrored estimate.
| Code | HTTP | When | Retry? |
|---|---|---|---|
credit_exhausted | 402 | A block plan's available funding cannot cover the request's economic maximum. | After a top-up or issuance. |
credit_state_unavailable | 503 | The funding projection for a block plan is absent or unreadable — fails closed. | Yes, transient. |
commercial_release_unprovable | 503 | The per-business release bundle is absent, incomplete, hash-invalid, scope-mismatched, or the emergency budget cannot cover the request. | Yes, transient. |
admission_descriptor_unavailable | 503 | The descriptor artifact is missing, corrupt, or from the wrong release / rating context. | Yes, transient. |
admission_descriptor_no_admissible_tuple | 503 | No conditional dimension tuple is consistent with the request. | Yes, transient. |
invalid_admission_knob | 422 | The client's output knob is malformed or has conflicting aliases. | No — fix the request. |
admission_bound_exceeded | 422 | The client's knob exceeds the admitted bound and cannot be safely rewritten. | No — lower the knob. |
Every one of these fails closed before any upstream call. Full vocabulary: Response & deny codes.
After the platform's billing cutover, a usage payload from an outdated
@farthershore/backend that lacks the served-identity block receives a
permanent 410/422 unsupported_usage_schema with
{ expected_schema_version, received_schema_version }. It is never
transformed, queued, quarantined, or backfilled. Upgrade the SDK.
If the edge cannot refresh its proof of the active release, it may keep serving
the last-verified cohort of the same release with a bounded emergency
reservation (stamped releaseProof: "emergency") for at most the lease-TTL
window; past that, or with an incomplete cohort, admission closes with
commercial_release_unprovable. See
Commercial releases.