Measurement · August 1, 2026
How much certificate can you afford?
The advice is to keep your post-quantum certificate chain under about 10KB. That number is real, but it is stated on the wrong quantity, and the budget it implies moves by more than two kilobytes depending on which signature algorithm signs your handshake.
If you have started planning a post-quantum migration, you have met a number: keep the certificate chain under roughly ten kilobytes, or the handshake costs an extra round trip.
The number is real and it comes from serious work. TCP’s initial congestion window holds about fourteen kilobytes on a standard path, so a server that needs to send more than that has to stop and wait for the client to acknowledge the first burst before it can send the rest. Matthew Chou and Phuong Cao measured exactly this across certificate sizes and found time-to-first-byte spiking “around 10KB and 40KB” of certificate chain. Panos Kampanakis and Will Childs-Klein at AWS got there in 2024, naming Certificate and CertificateVerify as the largest messages in the handshake and exploring whether tuning the TCP initial congestion window could compensate.
So the threshold is well established. What I want to point at is subtler, and it only shows up if you take the handshake apart message by message: the congestion window does not constrain your certificate chain. It constrains the whole flight. And the rest of that flight is not a constant. It changes size depending on which signature algorithm you picked, which means the certificate budget the number implies moves by more than two kilobytes between ML-DSA parameter sets.
I captured seven chain shapes and attributed every byte.
Where the bytes actually go
Each row is a real TLS 1.3 handshake against OpenSSL 3.5.5, captured and decrypted with a key log so every handshake message can be measured individually rather than inferred. “Flight” is everything the server sends before it can hear back from the client.
| Chain | Certificate | CertificateVerify | Other | Server flight |
|---|---|---|---|---|
| ecdsa | 914 | 74 | 1,256 | 2,244 |
| catalyst | 6,252 | 76 | 1,256 | 7,584 |
| mldsa44 | 8,112 | 2,424 | 1,256 | 11,792 |
| mixed | 7,922 | 3,313 | 1,256 | 12,491 |
| mldsa65 | 11,170 | 3,313 | 1,256 | 15,739 |
| slhroot | 15,717 | 3,313 | 1,256 | 20,286 |
| mldsa87 | 15,086 | 4,631 | 1,256 | 20,973 |
“Other” is ServerHello, EncryptedExtensions and Finished. It is 1,256 bytes in every single row, which is convenient: it means the only part of the flight that moves with your algorithm choice is CertificateVerify, the signature over the handshake transcript.
That signature is not small. ECDSA spends 74 bytes on it. ML-DSA-87 spends 4,631.
The budget moves
Put those together. At a standard 1460-byte MSS, ten segments is 14,600 bytes. Subtract the non-certificate part of the flight and you get the certificate chain you can actually afford:
| Signing algorithm | Flight minus chain | Chain budget under IW10 |
|---|---|---|
| ML-DSA-44 | 3,680 | 10,920 bytes |
| ML-DSA-65 | 4,569 | 10,031 bytes |
| ML-DSA-87 | 5,887 | 8,713 bytes |
There is no single ten-kilobyte number. There is a band from about 8.7KB to about 10.9KB, and where you land in it is decided by the parameter set signing your handshake, not by anything about your certificates.
Notice where ML-DSA-65 lands: 10,031 bytes. ML-DSA-65 is the common choice, and the budget it implies is almost exactly the ten kilobytes that Chou and Cao observed empirically. Their measurement and this attribution agree, which is the reassuring outcome. The per-message view does not overturn the published threshold. It explains where the threshold comes from, and it shows that the same threshold is 2.2KB tighter if you sign with ML-DSA-87 and 900 bytes looser if you sign with ML-DSA-44.
That has a practical consequence worth stating plainly. If you plan capacity against “keep the chain under 10KB” and then upgrade your signature algorithm for margin, you can consume the headroom you were relying on without touching a single certificate.
Catalyst is half the flight, for the reason it is unprotected
The catalyst row deserves attention. Its certificate is large, 6,252 bytes, because it carries an ML-DSA public key and signature inside non-critical X.509 extensions. But its CertificateVerify is 76 bytes, and its whole flight is 7,584 against pure ML-DSA-65’s 15,739. Less than half.
The reason is that catalyst’s post-quantum material is carried, never used. Authentication still happens with ECDSA, so the handshake signature stays classical and small. You pay to transport the post-quantum half and you never pay to sign with it.
That is the same property I wrote about in July from the compatibility side, where catalyst passed all eleven client stacks precisely because no deployed verifier checks its post-quantum half. It is cheap on the wire for the same reason it does not protect you. Compatibility, cost, and uselessness turn out to be three views of one fact.
The heaviest chain is not the heaviest handshake
This one corrects something I had written down myself. My earlier notes called the SLH-DSA-root chain the most expensive thing in the corpus, on the basis that its certificates are the largest, at 15,717 bytes against ML-DSA-87’s 15,086.
At the handshake level that is wrong. The SLH-DSA root signs the intermediate, but the leaf is ML-DSA-65, so the handshake signature is only 3,313 bytes. ML-DSA-87 signs its own handshake with 4,631. The totals invert: 20,286 against 20,973.
The most expensive certificate chain and the most expensive handshake are different rows in the same table. Worth knowing if you are optimising the wrong one.
Compression will not save you, and that is not news
The standard reply to all of this is certificate compression. It does not help, and the IETF has already said so twice.
From draft-ietf-uta-pqc-app: “its impact on PQ or PQ/T hybrid certificates is limited due to the larger sizes of public keys and signatures in PQC. These high-entropy fields, inherent to PQC algorithms, constrain the overall compression effectiveness.” From draft-ietf-tls-cert-abridge, post-quantum certificates “cannot be compressed with existing TLS Certificate Compression schemes because most of the size of the certificate is in high entropy fields such as cryptographic keys and signatures.”
I measured my corpus against all three algorithms RFC 8879 registers, at maximum effort, and the interesting part is not that compression underperforms but the shape of the failure. The saving is a constant. Every two-certificate chain in the corpus gave up between 205 and 252 bytes, a spread of 47 bytes, whether the chain was 900 bytes or 15,703. So the percentage collapses precisely as the certificates grow: 26.9% of the classical control, 1.5% of the heaviest post-quantum chain.
Splitting it shows why. Roughly 100 bytes compresses inside each certificate, which is X.509 boilerplate, and roughly 140 more compresses across the pair, which is the issuer name in the leaf repeating the subject name in the intermediate. Neither term scales with key or signature size. The single self-signed composite certificate in the corpus saves exactly zero across certificates, which is the control confirming that second term rather than assuming it.
One caveat has to travel with that number. My corpus is minimal by construction: short names, one SAN, two certificates, no SCTs, no OCSP or CRL URLs. Real WebPKI chains carry far more compressible structure, and cert-abridge measures a median real chain compressing from 4,032 to 3,243 bytes with zstd, a 789-byte saving. My 240 bytes is a floor for minimal certificates, not a WebPKI figure. The operational conclusion survives the correction, because the denominator grows faster than the saving does either way.
What I would do
Budget the flight, not the chain, and subtract your CertificateVerify before deciding how much certificate you can afford. The number is your MSS times ten, minus your handshake signature, minus about 1,256 bytes.
Re-check that budget whenever the signature algorithm changes, because that is the variable that moves it. Certificate hygiene is not what pushes you over; the parameter set is.
Do not plan capacity on certificate compression. Enable it, because the bytes are free, but a migration plan whose bloat answer is compression is planning to recover a low single-digit percentage of the problem it just described.
And if you are considering a catalyst-style hybrid because it is cheap on the wire, be clear with yourself that the cheapness and the lack of protection are the same property.
Provenance
Measured here (Verified). Every number in the tables comes from key-log-decrypted TLS 1.3 captures taken on 2026-08-01 on a single machine, with scripts and raw captures published at pqc-cert-matrix (DOI 10.5281/zenodo.21749600). Rerun any row and tell me if it disagrees.
Computed, not measured. Segment counts and the budget table are arithmetic on measured byte totals against a stated MSS and a ten-segment initial window. I did not measure segmentation, because the capture host has segmentation offload enabled, and a segment count read off that capture would be an artifact of offload rather than a property of the handshake. I also did not measure latency at all, so nothing here says how much an extra round trip costs you.
Cited, not claimed (Reported). The congestion-window threshold and its consequences are established work: Kampanakis and Childs-Klein (2024) for the initial-window interaction and for identifying Certificate and CertificateVerify as the largest handshake messages, and Chou and Cao (2026) for the measured time-to-first-byte thresholds. That post-quantum certificates resist compression is stated in two IETF drafts, quoted above. My contribution is the per-message attribution and what it implies about the budget, not the threshold itself.
Things I got wrong and have corrected. My own notes called the SLH-DSA-root chain the most expensive in the corpus; at handshake level it is not, and that is corrected above. While preparing this article I also found a web summary attributing a CertificateVerify byte figure to Delgado Jiménez’s placement study; that figure is not in his paper, and I have not repeated it. The repository carries a PRIOR-ART.md recording, per finding, what published work already covers. It has demoted several of this project’s claims, including two in this article, and it is the file to read before quoting any of this as new.
Not measured, recorded as open. Certificate compression never engaged in any capture despite both peers advertising zlib and zstd, which contradicts OpenSSL’s documented default behaviour. I have a hypothesis involving the missing brotli codec in this build and no evidence for it, so it stays an open item rather than a finding.
If something here is wrong, email the studio and I will correct it in place with a note saying what changed.