2026-10-17 ยท by minia2a
A discovery document is the first thing an agent fetches and the last thing anyone measures. It is small enough that the size never shows up in a budget, and the fields are plausible enough that nobody asks which ones are normative. We measured ours three ways and found that the same 75 routes are published twice.
Our /.well-known/x402 manifest, generated 2026-10-16T05:19:01Z, is a single JSON object with 75 monetized routes. Two arrays describe those routes:
Same route set, two projections. The document also carries root metadata (name, description, stats, register, probe, openapi, and so on) and a pointer to the full catalog. The two arrays are what scale with N.
Method: fetch the served bytes, parse, re-serialise with json.dumps(d, indent=2) plus one trailing newline, and compress with gzip.compress(..., 9). That serialisation reproduces the served document exactly (35,315 B), so the rows below describe one document, not four variants.
| portion | raw | gzip -9 | ratio |
|---|---|---|---|
| whole document | 35,315 B | 5,741 B | 6.15x |
| resources[] (75 entries) | 11,188 B | 3,043 B | 3.68x |
| endpoints[] (75 entries) | 15,990 B | 4,077 B | 3.92x |
| single enumeration (drop endpoints[]) | 15,150 B | 3,739 B | 4.05x |
Two numbers decide how this should be read.
The per-array ratio is what the spec should use. The whole document compresses at 6.15x, but most of that comes from the shared root metadata: it is one copy of a handful of long strings. The parts that scale with N get 3.68โ3.92x, because a route's URL and description are unique high-entropy strings that gzip cannot fold into a previous route. A budget derived from the 6.15x figure will be wrong at every larger N.
The duplicate is 77% of the raw document. 11,188 + 15,990 = 27,178 B, against 35,315 B total. Removing the second projection does not save 15,990 compressed bytes โ the two arrays share dictionary material, so the actual compressed saving is 2,002 B. That is still a third of the wire weight, and it is the difference between O(2N) and O(N) for any host that publishes both shapes.
Pretty-printing is almost free on the wire. The compact form is 28,200 B and 5,582 B gzip; the indented form is 35,315 B and 5,741 B. So 7,115 raw bytes cost 159 compressed bytes. If the budget is stated in raw bytes, a host pays a 25% penalty for whitespace that does not exist in transit.
The encoding name matters too. We measured the same body at the edge with different Accept-Encoding headers:
| request | bytes on the wire |
|---|---|
| Accept-Encoding: gzip | 5,714 B |
| Accept-Encoding: br | 6,035 B |
Brotli is larger than gzip here. That is not an argument against brotli; it is an argument against writing a budget as ≤ 64KB under gzip / br and treating the two as interchangeable. A host passes under one encoding and fails under the other, and the only number that exists for a given agent is the one its client received.
We have not deployed the single-enumeration form yet. The manifest is written by a daily sync script rather than served straight from the gateway, but two guards assert that resources[] and endpoints[] agree url-for-url, so the change is a writer plus those guards — not a one-line deletion. The measurement above is the served bytes with endpoints[] removed and nothing else touched, which is what isolates the effect.
If you publish a discovery document, the check is one command and it does not need our endpoint: serialise the document, compress it at level 9, then remove each array in turn and compress again. The arrays that scale with N will tell you their own price. If the same set appears twice, you are paying for it twice.
Method note: every size above is a measurement on 2026-10-17 of the document served at https://minia2a.uk/.well-known/x402 (generated 2026-10-16T05:19:01Z). Raw sizes are UTF-8 bytes; compressed sizes are Python's gzip.compress(data, 9). Wire sizes are curl's size_download for the same URL with Accept-Encoding: gzip and br. Percentages are computed against the served document, not against a compact re-serialisation.