Zero round trip early data
Zero round trip early data lets a returning client send a request in its first packet. It saves 1 round trip, 90 ms on this path. An attacker can replay that packet, so use it only for requests that are safe to repeat.
See it on the board
The same traffic runs on two boards. The simulator measured both when this page was built.
| Measure | Goal | Every request waits for the handshake | Early data for reads only |
|---|---|---|---|
| p99 latency | under 130 ms | 182 ms Fail | 92 ms Pass |
| Monthly cost | 4 USD/mo | 4 USD/mo | |
| Error rate | 0% | 0% |
Key numbers
| Number | Value |
|---|---|
| Round trips to open HTTP/3 (QUIC) | 1 RTT |
| Round trips to resume HTTP/3 | 0 RTT |
| Round trips to resume HTTP/2 | 2 RTT |
Early data for reads · round trips of 90 ms: 1 · 90 ms
How it works
A client that has talked to a server before holds a resumption ticket. With a ticket, the client can send its first request together with the handshake. The request arrives one round trip earlier. On a 90 ms path this saves 90 ms for each new connection.
The price is replay. Early data is not protected against a copy. An attacker on the network can record the first packet and send it again, and the server may run the request twice. A catalog read is safe to repeat. A payment write is not: a replayed packet can charge the customer twice.
So the rule depends on the request, not on the connection. Allow early data for reads and other requests that you can safely repeat. Make writes wait for the full handshake, or give them an idempotency key that the server checks. Transport encryption does not make a write idempotent.
In the mini board, the requests that wait for the full handshake have p99 182 ms and miss the 130 ms limit. When reads use early data, p99 is 92 ms. Payment writes still wait for the handshake, so no replay can create a second payment.
In the levels you decide which requests may use early data and check the read p99.