x402 Failure-Mode Benchmark
Three real x402 server implementations, tested black-box against the seven failure modes from x402 in production: the failure modes nobody warns you about. Every number below was measured on 2026-10-03. Cells that would require spending real money on-chain or contacting a live facilitator are labeled code inspection and cite the exact source. Nothing is estimated.
| # | Failure mode | Payload x402 kit 1.0.0 | x402-hono 1.2.0 | @x402/express 2.28.0 (official) |
|---|---|---|---|---|
| 1 | Replay: is a reused payment rejected? | No (live). Same dev-verifier payment accepted twice across different nonces; expired requirements also accepted. Replay protection is delegated to the facilitator/chain in production. | n/a in middleware (code inspection). v1 exact scheme relies on on-chain EIP-3009 nonce + validity window. | n/a in middleware (code inspection). Same EIP-3009 mechanism. |
| 2 | 402 completeness | Complete (live). 402 + payment-required header + JSON body; amount, asset, network, payTo, expiresAt, nonce all present. | Complete, body-only (live). accepts[] has scheme, network, maxAmountRequired, asset, payTo, maxTimeoutSeconds. No nonce field (v1 protocol). | Shape {x402Version, error, resource, accepts[]} (code inspection). No live test — needs a facilitator. |
| 3 | Manifest parity | 2/2 match (live). /.well-known/x402 prices equal enforced prices. | Absent (live). /.well-known/x402 → 404. | Absent (code inspection). Discovery via opt-in bazaar extension. |
| 4 | Facilitator down: fail open or closed? | Fail closed (live). 402 on refused connection (40 ms) and on hang (timeout honored, ~3000 ms as configured). | Fail closed on error (code inspection), but the verify fetch has no client-side timeout. | Fail closed (code inspection). |
| 5 | Dev-verifier boot guard | None (code inspection). The example boots with the dev verifier unconditionally; "never ship it" is documentation, not enforcement. | n/a — no dev verifier exists. | n/a — no dev verifier exists. |
| 6 | Mismatch diagnostics | Reason strings (live). amount mismatch, wrong asset or network, wrong recipient in the 402 body; no structured expected/actual fields. | Malformed → 402 with decoder error (live). Amount matching happens in the facilitator, not the middleware (code inspection). | Not tested (needs facilitator). |
| 7 | Payment ledger | Yes (live). Append-only JSONL; /api/ledger endpoint; +2 paid calls → +2 entries. | No (code inspection). | No (code inspection). |
What this means
The differences mostly reflect protocol generation (v1 vs v2) and scope (focused middleware vs full SDK), not a ranking. The Payload kit is the only implementation of the three with a manifest endpoint and a payment ledger; the official SDKs delegate replay protection and amount validation to the facilitator and the chain, which is the correct design for production but means those paths can't be verified without spending real money.
One honest correction: the companion dev.to article claims "the verifier rejects expired or already-seen nonces" — that does not hold for the kit's dev verifier in v1.0.0, as measured above. The dev verifier is a test double; production replay protection comes from the facilitator.
Reproduce it
All probe scripts and machine-readable results: github.com/Payloadhq/x402-failure-mode-benchmark — /probes (runnable) and /results/results.json. MIT licensed.