The body waits for the money
Three fixes landed in the x402 SDKs in one week and all had the same shape: hold the whole response until the payment settles. That is not a bug class. It is what a payment protocol does to a serving path when the money is the last thing to happen.
The argumentBecause x402 settles after the handler has run and reports the result in a response header, getting paid now costs the server the entire response held in memory, and the scheme written for token-metered AI billing is precisely the one that cannot avoid it.
A pull request merged into the x402 repository on 4 September carries a title that could pass for housekeeping: fix(java): buffer response body until settlement succeeds in PaymentFilter. The description is less relaxed. PaymentFilter.doFilter(), it explains, "calls chain.doFilter() directly against the real HttpServletResponse, so the protected handler's output is written — and often committed — to the client before facilitator.settle() runs." The paid thing was leaving by the front door before anyone knew whether the money had moved. The fix wraps the response, runs the handler against the wrapper, and flushes the real one only after settlement confirms. If it does not confirm, the buffered body is discarded and the caller gets a 402.
Three days later the TypeScript adapters were given the same treatment. Hono and Next, the patch records, "were returning the unread Response.clone() branch after processSettlement, so a long settle could deliver an empty or already-read body." They now "consume the handler body (including streams) before settle and reply from that buffer only after confirmation." The same change raised the default facilitator HTTP timeout from thirty seconds to ninety. On 8 September the Go client followed, for a reason stated without drama: "Long settle() calls can exceed the old 30s default."
Three fixes, five days, three languages, one shape.
It would be reasonable to read that as a project sweeping a bug class across its SDKs, which is what a healthy project looks like. I think it is something more interesting, and the evidence for it is in the specification rather than the patches. x402's default payment flow settles after the resource has run, and the HTTP transport reports settlement in a response header. Headers precede bodies. Those two decisions were taken separately and each is defensible on its own; together they require a server to hold the entire response in memory until a payment network agrees the money is real. The buffer is not three implementations getting the same thing wrong. It is the protocol's shape, arriving.
Section 6.1 of the v2 specification is unusually candid about this, because it makes the ordering an explicit, named part of the protocol rather than an emergent property. Three flows are defined. In authorization, the default, the ordering is verify → resource → settle → respond: a read-only check runs first, and "funds move only after it completes successfully." In upfront, it is settle → resource → respond, which gives "the server finality first" and is, the spec notes, "required by networks with no pull-settlement primitive." In escrow, settle → resource → settle → respond, a deposit is committed, the work happens, and a second settle records the final charge. One invariant binds all three: at least one check must run before the resource does. "The resource never executes with nothing checked."
Read that table as a risk allocation and it becomes a different document. Each row answers the oldest question in commerce — who hands over first — and answers it differently. Under authorization the seller does the work before the money is certain and eats a settlement failure. Under upfront the buyer pays before the work happens and eats a handler failure. The specification tells clients to "prefer authorization" where both are offered, which is a sensible default and also an admission of what the alternative costs them.
Now put the HTTP transport beside it. Settlement results travel in a base64-encoded PAYMENT-RESPONSE header. Under authorization that header cannot be written until the handler has finished and the facilitator has answered, which is exactly why the SDK adapters had to consume the body — "including streams" — before settling. The transport specification defines no trailer for this, and trailers are unreliable through the proxies and CDNs that sit in front of anything worth charging for. So the mechanism is not merely that x402 servers currently buffer. It is that a server which streams cannot report settlement in the place the protocol puts it.
Which brings the argument to the part that matters for anyone building on this. The scheme x402 designed for metered AI billing is the one that cannot escape the buffer. upto authorises a maximum and settles the actual amount consumed; its first listed use case is "paying for LLM token generation (charge per token generated)." Its own specification closes the door explicitly: "upto cannot use upfront because the settled amount is known only after the route handler runs, so settlement cannot precede resource execution." Metered generation is therefore pinned to post-execution settlement, post-execution settlement puts the money in a header, and the header holds the body. The single latency number that defines the experience of generated text — time to first token — is the number this arrangement makes unavailable.
The ninety-second timeout should be read in that light rather than as a tuning parameter. It is the project's own estimate of how long a settle call may legitimately take, and it now sits inside the request path, with a completed response waiting behind it. A tail that used to be governed by your model and your GPU is now also governed by a chain's confirmation behaviour and a facilitator's availability, and the memory to hold every in-flight answer is a capacity line nobody had budgeted. The error taxonomy makes the ambiguity official: settlement_pending is a non-terminal code meaning the transaction was broadcast but confirmation could not be established, and the caller "can reconcile on chain before deciding whether to retry." That is a request which is neither paid nor unpaid, holding a response that is neither delivered nor discarded.
There is a second-order allocation here that deserves more attention than it is getting. Which flow you end up in is not primarily a commercial decision. The specification's own example distinguishes "an SVM upto escrow default from an EVM upto authorization default" — the same scheme, the same product, the same price, and a different party bearing the loss on a half-finished request, decided by which chain the seller happens to settle on. The 2 September change that formalised upfront for proof-style payments is explicit about why: some methods "MUST use upfront: the payment is already final when the payload is presented." Not because anyone judged the buyer better placed to absorb the risk, but because the rail has no way to pull funds later. Risk allocation has been delegated to a settlement primitive.
Recourse exists, and it is worth being precise about its shape. The auth-capture scheme, updated to v1.1 on 25 August, adds a real lifecycle: hold, capture, void, refund, reclaim. But the specification is clear that charge, capture, void and refund "are not client-authorized" — they are initiated by the resource server and relayed by the facilitator. The buyer's only unilateral move is reclaim, recovering its own hold after the capture deadline passes on funds the seller never took. And the question of who funds a refund at all is still listed among the things each network binding must specify: "who supplies refund liquidity, given that a facilitator must not be an unexpected source of value." Meanwhile the core specification puts "client-side budget management" out of scope entirely. A fleet of agents sharing a wallet has no protocol-level ceiling and no protocol-level chargeback.
The strongest case against this reading is that the trade is disclosed and deliberate. The repository's technical goals list, in as many words, the "ability to trade off speed of response for guarantee of payment." Buffering responses is what API gateways, WAFs and serverless runtimes have always done; almost nothing behind a paywall streams today; and a project that found an unpaid-content leak in three SDKs inside a week is a project whose review process works. On that view the patches are evidence of health, not of a design flaw, and the alternative — thirty platforms each inventing their own settlement ordering — is plainly worse.
I would grant most of that, and the last point entirely. But the disclosed trade is written as the server's choice about its own payment guarantee, and what it actually purchases is a change in the buyer's experience that the buyer never sees priced. More to the point, "nothing streams" is true of the web x402 grew out of and false of the market it is aimed at. Agents buying generated text from other agents is the use case the upto scheme names first, and it is the one where the response is long, incremental, and consumed as it arrives. This reading is built entirely from one project's own record — its specifications, its patches, its stated goals — because that record is unusually complete and because the deployments that would corroborate or refute it are not public.
What the whole episode illustrates is that a payment rail is not a layer you add beside a system. It is a control-flow constraint you add inside one. Charging at the request boundary means the money becomes the last thing that happens, and everything the customer experiences queues behind it. We spent two decades pushing commerce out of the request path precisely to avoid that — into subscriptions, prepaid credits, invoices, monthly reconciliation — and the reason was never bookkeeping convenience. It was that credit is what lets delivery and payment run on different clocks. Per-request settlement recouples them, and the coupling shows up as buffered bytes and a ninety-second timeout.
So somewhere in a server's memory there is a finished answer that a customer has paid for, waiting for a chain to agree that they have. The specification calls that state settlement pending. Everyone downstream of it will call it latency, and nobody will know why.
What this is argued from
Reporting and primary material the piece rests on, dated at the time of writing. The interpretation is mine; the facts belong to these.
- x402 Protocol Specification v2
- x402 HTTP transport specification
- fix(java) buffer response body until settlement succeeds in PaymentFilter (PR #3074)
- fix(ts) patch hono/next buffers and raise facilitator timeout (PR #3392)
- fix(go) raise HTTPFacilitatorClient default timeout to 90s (PR #3408)
- Scheme upto
- Scheme auth-capture v1.1
- Expand asset transfer methods with upfront payment flows (PR #3145)
Editorials on this site are written to be argued with. If you think the reading is wrong, it probably is in some particular way, and that is the useful part.