A probe of 2026-09-25 measures four exchanges. It writes and reads back each frame of GraphTP/1 with a prototype of the crate graphtp, and records HTTP/1.1 between the fetch of Node.js 24.13.0 and a GraphQL server on Node.js. The query {__typename} takes 60 bytes of request and answer over GraphTP/1 and 520 over HTTP/1.1, whose request head takes 278 bytes and answer head 187, where GraphTP/1 writes 3 and 2. GraphTP codes a request of >128 B as well, so the introspection request of 2,060 bytes travels in 428, while HTTP/1.1 sends it plain, 2,340 bytes with its head. A content or a body of exactly 128 bytes travels plain and one of 129 bytes coded. The notebook 24_graphtp writes the first three exchanges through the crate graphtp in the same 60, 346 and 175 bytes, and a full introspection document of its own, 1,206 bytes of JSON, travels in 375, while the columns of HTTP keep the numbers of the probe.
HPACK narrows the gap. On a connection in use HTTP/2 finds the fields it has sent before in the dynamic table of HPACK and names each in about a byte, so the same query takes 129 bytes over HTTP/2, and 261 on its first exchange. On Network with IPv4, GraphTP(Homa) takes 212 bytes in two IP packets with the full header of Homa, HTTP/2 on TCP 233 and HTTP/1.1 624, so GraphTP saves 21 bytes against a warm HTTP/2 connection. GraphTP sends the credential in every request and never compresses it, against the attacks CRIME and BREACH, while HPACK indexes it after the first request: with a Bearer token of 71 bytes a repeated {__typename} takes 131 bytes over GraphTP/1 and 130 over HTTP/2. The introspection answer is 19 bytes longer over GraphTP/1 than the whole answer of HTTP/1.1, because GraphTP codes with a window of 4 KiB and the recorded server gzips with one of 32 KiB. The fetch of Node.js names gzip and deflate, so the HTTP server of Aosabi answers it with deflate in the zlib format, whose wrapper takes 6 bytes where the one of gzip takes 18. GraphTP has no handshake, so a first exchange with a new peer costs what the table shows, while HTTP/1.1 on a new TCP connection adds 172 bytes and a round trip and HTTP/2 109 bytes of preface and settings, and TLS adds its own where it runs.
Clients write more than a request needs. RFC 9110 asks a user agent to send a User-Agent field in each request unless it is configured not to. The fetch of Node.js sends User-Agent, Accept-Language and Sec-Fetch-Mode in the recorded request, 60 bytes, and names itself node in 18 of them. Version 2.34.2 of the requests library of Python sends python-requests/2.34.2, a line of 36 bytes, and Chrome on Windows, whose major version has three digits since version 100, sends a line of 125 in the reduced form Chromium documents, on every request. GraphTP carries no field, the user agent among them, and the one value of HTTP's fields it carries is the credential. Naming a coding costs GraphTP no byte: the compressed bit of the request head and the first byte of the body of an answer name it, where Accept-Encoding takes 32 bytes of the recorded request.
The crate graphtp is shaped like the crate http. It holds the types and the codec of GraphTP/1 and nothing that moves a byte, with no standard library, no dependency and no feature, so its zlib encoder and decoder are part of every build. The binding to Homa is the crate graphtp-homa beside it, as hyper stands beside http, and GraphTP is specified apart from Aosabi, so any GraphQL server and client can implement it. A prototype of the crate, built for size, adds 9,695 bytes of code and constant data on riscv32imc-unknown-none-elf, the target of the ESP32-C3, and 11,648 on aarch64. On both targets the two heads with the status mapping stay below 500 bytes, and the encoder takes about two thirds of the codec. That is less than the types of the crate http 1.5.0 alone, 19,664 bytes on aarch64, and less than half of the compression crate miniz_oxide 0.8.9. The crate itself, as the notebook 24_graphtp measures it, takes 19,264 bytes by the object file on riscv32imc and adds 16,040 with its unwind tables to an image on aarch64, where the prototype adds 13,632, and its two heads with the status mapping take 364 and 440 bytes of code. The HTTP/1.1 server path of hyper 1.11.0 takes 110,168 bytes on aarch64 in an earlier probe for the plan of M5, and the server path of the fork of hyper 1.11.1 with its Node connection takes 97,796 bytes on the ESP32-C3, as the notebook 35_esp32c3_http_vs_graphtp measures it in the benchmark build of the card. Measured on an ESP32-C3 simulated in QEMU, the image of Aosabi in Rust with a song app takes 1,037,120 bytes, 0.99 MiB and so under 1 MiB, 9,764 of them for the app, and answers a request for a song, its artist and the artist's songs over GraphTP(Homa) on the Serial Line at 115,200 baud in one round trip, 300 bytes and 32.4 ms of line and computing time, a lower bound for a real chip, since the computing time counts one cycle per instruction. The same app as REST on hyper with HTTP/2 and TLS 1.3 on ESP-IDF takes an image of 858,224 bytes and, timed the same way over plain HTTP/1.1, three round trips, 827 bytes and 72.6 ms.
The service reads the query text fast. GraphTP carries the query text, and the service parses and validates it as it does over HTTP. On one core of an Apple M1 Max the parser of Aosabi, translated from graphql-js 16.12.0, parses about twice as fast as graphql-js since the item LANG2 of the roadmap closed on 2026-10-01: the Feed query in 2.47 µs against 5.85 and the introspection query in 7.08 against 16.81, and one parse of the introspection query allocates 37 times where it allocated 122 before. Since the item PASS1 closed on 2026-10-21 a single pass compiled from the schema takes the seat of the validator by default, and the rules of the validation answer every document it refuses or defers, so every answer stays the same. Japanese text travels byte for byte: kanji stand raw in UTF-8 in string values, variables, descriptions and every JSON body, a line and a column count UTF-16 code units as graphql-js counts them, the 64 Japanese documents of the notebook 02_language parse as graphql-js parses them, and the 11 Japanese bodies of the capture come back byte for byte after decoding, plain or coded.