v0.x

QPACK in ten minutes

How HTTP/3 compresses headers without reintroducing head-of-line blocking.

HTTP/2 compressed headers with HPACK, which relies on both sides updating a shared table in exactly the same order. Over TCP that is free — bytes arrive in order. Over QUIC, streams are independent, so a table update on one stream could arrive after a request on another stream that depends on it.

Two tables, two control streams

QPACK (RFC 9204) keeps the static and dynamic tables, but moves dynamic-table updates onto a dedicated encoder stream, with acknowledgements on a decoder stream. A request that references an entry the decoder has not seen yet is blocked — and the encoder decides how many such blocked streams it is willing to risk.

The safe default

An encoder can always choose to reference only the static table and literals. It compresses less, but it never blocks. QUICO starts there and uses the dynamic table only when the peer advertises room for it.

javascript
const settings = {
  qpack_max_table_capacity: 4096,
  qpack_blocked_streams: 16
};

Those two settings, sent on the control stream at the start of the connection, are the whole negotiation.

colocohen

Author of QUICO, LemonTLS and a family of pure-JavaScript network servers.