The TLS handshake: what the first connection pays for
"Session resumption saves a round trip" is a TLS 1.2 sentence that people keep saying about 1.3. Measured over a link with a known delay: a full 1.3 handshake costs one round trip, a 1.2 handshake two, and resumption in 1.3 saves none. What it does save shows up in the bytes.
Full technical treatment
TL;DR
Before the first byte of data the two sides agree on things, and agreeing costs waiting rather than CPU work. The client makes sure the server is who it claims to be, and both sides derive a shared key — and every such step needs a flight to the server and back. It is paid once per connection, not per request.
Hence the main consequence: "TLS is slow" is a statement about distance, not about encryption. Symmetric encryption of the data did not enter the measured price at all: the whole of it is the round trips of setup and the bytes of the certificate. Measured: 43.6 ms against a 40 ms round trip, one round trip at setup — and a reused connection does not pay it at all, which is why "the first request is slow" is not an anomaly but exactly this price.
Beyond that is what separates knowing from having read. A full TLS 1.3 handshake costs one round trip and a TLS 1.2 handshake two: measured over a link with 20 ms of delay each way, 43.6 ms against 84.7. Resumption saves a round trip only where there was one to save: in TLS 1.2 two became one (42.3 ms), in TLS 1.3 one stayed one — 43.6 against 42.2 — and both sessions really were resumed. What it saves instead is the certificate: in TLS 1.2 the server sent 1453 bytes on a full handshake and 172 on a resumed one, 8.4 times fewer. Only 0-RTT removes the wait before data is sent, and the RFC names the price: there are no guarantees of non-replay between connections, so an operation with a side effect does not go into early data unless the application itself defends against a replay. And the boundary of the number itself: one round trip is the price of the handshake on top of an already established TCP connection, not of a whole HTTPS connection from scratch.
- data does not travel instantly: an answer arrives after a delay, and the further away the peer, the larger that delay;
- before talking to a server, a client establishes a connection to it;
- traffic on a network can be read and altered by whoever carries it, and encryption is the defence against that.
- the order of handshake messages and how the versions of the protocol differ;
- session resumption, tickets, 0-RTT, early data, forward secrecy.
What this question is really about
The ladder looks like this:
- "What happens when a TLS connection is established?" — the warm-up about the handshake.
- "What does it cost?" — the substance starts here: it costs round trips, not percentages of a CPU.
- "What does session resumption buy?" — the question most often answered with a sentence from the days of TLS 1.2.
- "What is 0-RTT and why is it not turned on for everyone?" — a question about a price the standard states itself.
- "Why is the first request to a service slower than the rest?" — a question about the handshake being paid per connection.
- "Should TLS be turned off inside the perimeter for speed?" — a trap: the thing to measure is not the thing that seems obvious.
The numbers come from running bench/tls/handshake.py and
bench/tls/practice.py. There is no real server on the internet here: its
delay is unknown and unstable, and round trips are what has to be measured. Instead there is a server on loopback
and a link that delays every chunk by exactly 20 ms each way. The round trip is
therefore known exactly, and the handshake time reads in round trips.
Base: what the two sides agree on, and what a connection is made of
Before counting round trips and comparing versions it is worth naming, in ordinary words, what this exchange is for at all. The client wants three things out of it, and none of them comes for free:
- to be sure the server is who it claims to be — otherwise there is nobody to encrypt with: a channel to an impostor encrypts every bit as well as a channel to the real thing;
- to agree on keys that neither side had before this conversation;
- to get encryption and tamper protection out of those keys — so that whoever carries the traffic can neither read the data nor quietly change it.
Agreeing on anything with a peer at a distance cannot happen faster than a message flies there and back. So the price of a handshake is not CPU work but waiting: so many flights out and back before the first byte of the request leaves. Such a flight is called a round trip from here on, and round trips are what this lesson counts.
And a second thing, without which the arithmetic below reads wrong: the TLS handshake is not the whole connection but one step of it. A new HTTPS connection to a server is made of four:
- name resolution — the server's address is found from its name (the previous lesson);
- establishing the TCP connection — an exchange of its own over the same link, with round trips of its own;
- the TLS handshake — what this lesson counts;
- the request and its answer — what all of it was for.
Hence what governs every number below: "TLS 1.3 fits into one round trip" is a statement about the third step, not about the connection as a whole. It does not cancel the round trips of the first two, and a new HTTPS connection pays for all four.
That is already enough to answer the basic interview question. Beyond it comes how many round trips the third step costs in each version, what session resumption changes about that, and what it does not.
Mechanism 1: a handshake costs round trips
The round trips from the Base are a unit of measure rather than a figure of speech: quoting the price of a handshake in milliseconds is meaningless, because that price is set entirely by how far away the server is. Everything else is small against it.
To see round trips, their length has to be known. Here it is set: between the client and the server sits a relay that delays every chunk by 20 ms each way.
1. A FULL HANDSHAKE COSTS ROUND TRIPS, AND THE VERSION DECIDES HOW MANY
-----------------------------------------------------------------------
version handshake, ms in round trips reused
TLS 1.3 43.6 1.1 False
TLS 1.2 84.7 2.1 False
The same link, the same certificate, the same server. The only difference is the version of the protocol — and it is exactly one round trip.
Why. In TLS 1.2 the content of the client's half of the key exchange depends on what the server chose:
The ClientKeyExchange message is now sent, and the content of that message will
depend on the public key algorithm selected between the ClientHello and the
ServerHello.
So it cannot be sent before the server answers — hence the extra round trip. In TLS 1.3 the client guesses the server's choice in advance and sends its half straight away, and the server answers with the key already made.
"Guesses" is not a figure of speech: if the guess does not fit, the server asks for a retry and the handshake costs two round trips, as in 1.2. In this measurement the guess fitted, hence 1.1 round trips.
Hence the practical point this mechanism gets asked about: half of the received wisdom about TLS is about 1.2. Before repeating a figure, it is worth asking which version it is about.
Mechanism 2: resumption does not always save a round trip
Now the sentence itself. "Session resumption saves a round trip" gets said almost every time. Test it on both versions.
2. RESUMPTION SAVES A ROUND TRIP ONLY WHERE THERE WAS ONE TO SAVE
-----------------------------------------------------------------
version full, ms resumed, ms full resumed reused
TLS 1.3 43.6 42.2 1.1 1.1 True
TLS 1.2 84.7 42.3 2.1 1.1 True
In TLS 1.2 the sentence is true: two round trips became one, 84.7 ms turned into 42.3.
In TLS 1.3 it is false: one round trip stayed one — 43.6 against 42.2. There was nothing to save.
And the important part is the reused column. Both rows say True: the session
really was resumed, in 1.3 too. So the point is not that resumption failed but
that there is no round trip left for it to save.
Hence the answer that separates someone who measured from someone who repeated: "in 1.3 resumption saves no round trip, because the full handshake already costs one; what it saves is something else".
Mechanism 3: what resumption actually saves
That something else is bytes, and the biggest of them is the certificate. The same relay counts the stream in both directions:
3. WHAT RESUMPTION ACTUALLY SAVES: THE CERTIFICATE
--------------------------------------------------
version handshake client -> server server -> client
TLS 1.3 full 620 1871
TLS 1.3 resumed 659 520
TLS 1.2 full 640 1453
TLS 1.2 resumed 598 172
The column to read is the right-hand one. In both versions the certificate
is sent by the server — RFC 5246 says so directly: Following the hello messages, the server will send its certificate in a Certificate message if it is to be authenticated
. That is why it is the server's stream that changes, and the measurement
shows by how much. In TLS 1.2 it falls from
1453 bytes to 172 — 8.4 times. In TLS 1.3 from 1871 to 520.
The stream from the client barely changes: it has nothing large to send even on a full handshake.
The practical point. A real certificate chain is not one self-signed certificate but two or three real ones, that is, kilobytes. Resumption removes them entirely. On a fast link that is invisible; on a slow or metered one it can be worth more than the round trip that was saved.
And a flip side worth raising yourself: resumption needs state. The client has to keep a ticket and the server has to be able to accept it. A ticket is issued by one particular server, so a load balancer handing connections to different servers turns resumption back into a full handshake wherever those servers share no secret for tickets — neither a store nor the key the ticket is encrypted under. There is no measurement of this in the lesson: it follows from one side issuing the ticket and another accepting it. Only someone watching the share of resumed handshakes, rather than the average time, will notice.
Mechanism 4: it is paid per connection, not per request
The last mechanism is about where all this arithmetic lands in a real system. The run block here is the fourth and last.
4. WHAT ENCRYPTION COSTS AGAINST NO ENCRYPTION AT ALL
-----------------------------------------------------
connection connect, ms handshake, ms exchange, ms
plain TCP 0.3 - 41.6
TLS 1.3, full 2.1 43.6 81.6
TLS 1.3, resumed 0.8 42.2 61.3
the handshake alone, round trips 1.1
The column to read is handshake: one round trip, and that is the whole
price of encryption at this layer. Symmetric encryption of the data itself did
not enter the measured difference at all — at these volumes it is not visible.
And here is what matters: that round trip is paid once per connection. Not per request, not per kilobyte. A client that keeps a connection open and sends a hundred requests through it pays the handshake once out of a hundred.
Hence the right reaction to "the first request is slow": it is not an anomaly and not a reason to fix TLS. It is exactly the price visible in the table, and it is removed not by turning off encryption but by reusing the connection — along with the name resolution from the previous lesson, which a reused connection also skips.
And the same table shows the boundary of the number, which is what the plain TCP
row is there for. The connect column is a connection to the link standing on
the same machine: 0.3 ms, with no round trip in it at all. So "one round trip"
is the price of a handshake on top of an already established TCP connection,
not the price of connecting from scratch. A real new connection first resolves
the name, then establishes TCP — with round trips of its own over the same
link — and only then starts the handshake. Reading the TLS 1.3, full row as
"an HTTPS connection costs one round trip" does not follow: those 43.6 ms cover
only the third of the four steps named in the Base.
Deeper: only 0-RTT removes the wait before data, and its price is stated
Given that in TLS 1.3 a full handshake costs a round trip and a resumed one also costs a round trip, the question remains: can that wait be skipped before data goes out? It can: the handshake still costs a round trip, but some application data leaves with the very first message. The standard names the mode and the price in one sentence:
A zero round-trip time (0-RTT) mode was added, saving a round trip at connection
setup for some application data, at the cost of certain security properties.
"At the cost of certain security properties" — and here is which ones:
There are no guarantees of non-replay between connections.
That is the answer to "why is 0-RTT not turned on for everyone". Early data can be captured and sent again, and the protocol makes no promise that the server will notice: measures against replay are left to the implementation, so the worst case is what to plan for. For "show me a page" that means nothing. For "take the money" it means everything.
Hence the rule, and it is better stated from the risk than from a list of permitted methods: that very first message can be replayed, so an operation with a side effect does not go into early data — not unless the application itself defends against a repeat. This is the same boundary as in the lesson on retries: there the repeat was made by the client, here by an attacker, and the defence is the same.
The standard names a second price, mentioned less often:
This data is not forward secret, as it is encrypted solely under keys derived
using the offered PSK.
That is, captured early data can be decrypted later if an adversary obtains that key. Ordinary connection data does not have this property.
How to answer in an interview
Short answer: a handshake costs no CPU work worth mentioning but round trips — flights to the server and back — and it is paid once per connection rather than per request. How many round trips depends on the version: TLS 1.3 one, TLS 1.2 two. Measured over a link with a known round trip: 43.6 ms against 84.7 for a full handshake. So "the first request is slow" is cured by reusing the connection, not by turning encryption off.
That is enough to answer correctly. Beyond it is what to add if the interviewer digs.
If the interviewer digs deeper
Three things separate a good answer. First, you know what session resumption buys in each version: it removes a round trip only in 1.2 — 84.7 ms turn into 42.3 — while in 1.3 there is none to remove, 43.6 against 42.2. What it saves there is the certificate instead: in 1.2 the server's stream falls from 1453 bytes to 172. Second, you name the price of 0-RTT in the standard's words: there are no guarantees of non-replay between connections, so an operation with a side effect does not go into early data unless the application itself defends against a repeat. Third, you mention that resumption needs state on both sides, and that behind a load balancer it works only where the servers share a secret for tickets.
And one thing that is easy to overstate. Saying "a new HTTPS connection costs one round trip" carries the measured number further than it reaches. One round trip is the TLS handshake on top of an already established TCP connection; connecting from scratch also pays for name resolution and for establishing TCP, and over a distant link those steps cost round trips of their own. Stated precisely: one round trip is the price of the third step out of four, not of the whole connection.
What not to say: "TLS adds so many percent". That number means nothing: the price of a handshake depends on the round trip to the server rather than on the volume of data, and it differs by orders of magnitude between links.
Next they ask
Does turning TLS off inside the perimeter help?
Less than it seems, and not where it seems. The measured price is one round trip per connection. Inside a data centre a round trip is tens of microseconds, and one of those on a connection that lives for minutes is invisible.
It becomes noticeable in two cases: when connections are short and a new one is established per request, and when the round trip is large. The first is fixed by reusing connections, the second by placement — not by turning off encryption.
Why does resumption sometimes not happen?
Because it needs state on both sides: the client keeps a ticket and the server has to be able to accept it. A client that creates a new context per request loses the ticket and does a full handshake every time.
On the server side the same thing is broken by balancing: if one server issued
the ticket and the next connection lands on another that shares no ticket secret
with it, the ticket is not accepted. This is watched not through average time but through the
share of resumed handshakes — the reused column in the measurement.
Which costs more: the handshake or verifying the certificate?
In this measurement they cannot be compared: the client here does not verify the certificate at all. The subject of the measurement is round trips and bytes; the cost of checking a signature is not part of it.
But the direction is known from how they work: a round trip is the delay of a link, measured in milliseconds and growing with distance; verifying a signature is CPU work, measured in tens of microseconds and independent of distance. So on an intercontinental link the round trips decide everything, while on loopback the verification starts to show. Measure your own ratio; do not assume it.
What is sent on resumption instead of the certificate?
A ticket the server issued during a previous connection — in effect a reference to an already agreed secret. That is why the server's stream falls several times over: there is no need to prove identity again.
An important detail for TLS 1.3, and an easy one to get wrong: the ticket is sent after the handshake, in a separate message. A client that closes the connection right after the handshake never receives the ticket and will do a full handshake next time without saying anything about it.
Common misconceptions
Session resumption saves a round trip
Only in TLS 1.2. Measured: there two round trips became one (84.7 ms against 42.3), while in TLS 1.3 one stayed one — 43.6 against 42.2. The reused column says True in both rows: resumption worked, there is simply no round trip left for it to save.
TLS is slow because encryption is expensive
The measured price is one round trip per connection, that is, the delay of a link rather than the work of a CPU. Symmetric encryption of the data itself did not enter the difference at all. "Slow" here means "far away", and it is cured by reusing connections rather than by turning encryption off.
0-RTT is just a faster mode
It is a mode with different guarantees, and RFC 8446 names them directly: There are no guarantees of non-replay between connections
. That very first message can be captured and sent again, and the protocol makes no promise that the server will notice, so an operation with a side effect does not go into early data unless the application itself defends against a repeat.
A new HTTPS connection costs one round trip
What fits into one round trip is the TLS 1.3 handshake, and that on top of an already established TCP connection. Connecting from scratch has four steps — name resolution, establishing TCP, the TLS handshake and the request itself — and the first two pay round trips of their own over the same link. They are not inside the measured 43.6 ms: the connect column in the run is a connection to the link on the same machine, 0.3 ms.
The handshake is paid on every request
Per connection. Measured: the handshake took 43.6 ms against a 40 ms round trip, one round trip at setup. A client that keeps a connection and sends a hundred requests through it pays the handshake once out of a hundred — which is why "the first request is slow" is not an anomaly but exactly this price.
Resumption costs nothing and happens by itself
It needs state on both sides: the client keeps a ticket, the server can accept it. A client with a new context per request loses the ticket; a load balancer hands the connection to a server that shares no ticket secret with the issuer, and it is not accepted. Both are visible only through the share of resumed handshakes, not through average time.
Practice
Two exercises. Answer first, then check against the real output: in both, the correct answer is what the measurement script prints.
Practice · predict the output
full13, resumed13, _ = pair(key, crt, ssl.TLSVersion.TLSv1_3)
full12, resumed12, _ = pair(key, crt, ssl.TLSVersion.TLSv1_2)
print(f"{full13['handshake_ms'] / RTT_MS:.1f}")
print(f"{full12['handshake_ms'] / RTT_MS:.1f}")
print(f"{resumed13['handshake_ms'] / RTT_MS:.1f}")Practice · estimate
Knowledge check
How many round trips does a full TLS 1.3 handshake cost?
This is neither a retelling nor a separate text: everything below is taken from the article itself — its own summary, the section headings, the “actually” column and the version table. Which is why these theses cannot drift from the article.
The gist
- Before the first byte of data the two sides agree on things, and agreeing costs waiting rather than CPU work. The client makes sure the server is who it claims to be, and both sides derive a shared key — and every such step needs a flight to the server and back. It is paid once per connection, not per request.
- Hence the main consequence: "TLS is slow" is a statement about distance, not about encryption. Symmetric encryption of the data did not enter the measured price at all: the whole of it is the round trips of setup and the bytes of the certificate. Measured: 43.6 ms against a 40 ms round trip, one round trip at setup — and a reused connection does not pay it at all, which is why "the first request is slow" is not an anomaly but exactly this price.
- Beyond that is what separates knowing from having read. A full TLS 1.3 handshake costs one round trip and a TLS 1.2 handshake two: measured over a link with 20 ms of delay each way, 43.6 ms against 84.7. Resumption saves a round trip only where there was one to save: in TLS 1.2 two became one (42.3 ms), in TLS 1.3 one stayed one — 43.6 against 42.2 — and both sessions really were resumed. What it saves instead is the certificate: in TLS 1.2 the server sent 1453 bytes on a full handshake and 172 on a resumed one, 8.4 times fewer. Only 0-RTT removes the wait before data is sent, and the RFC names the price: there are no guarantees of non-replay between connections, so an operation with a side effect does not go into early data unless the application itself defends against a replay. And the boundary of the number itself: one round trip is the price of the handshake on top of an already established TCP connection, not of a whole HTTPS connection from scratch.
In fact
- Only in TLS 1.2. Measured: there two round trips became one (84.7 ms against 42.3), while in TLS 1.3 one stayed one — 43.6 against 42.2. The
reusedcolumn saysTruein both rows: resumption worked, there is simply no round trip left for it to save. - The measured price is one round trip per connection, that is, the delay of a link rather than the work of a CPU. Symmetric encryption of the data itself did not enter the difference at all. "Slow" here means "far away", and it is cured by reusing connections rather than by turning encryption off.
- It is a mode with different guarantees, and RFC 8446 names them directly: There are no guarantees of non-replay between connections. That very first message can be captured and sent again, and the protocol makes no promise that the server will notice, so an operation with a side effect does not go into early data unless the application itself defends against a repeat.
- What fits into one round trip is the TLS 1.3 handshake, and that on top of an already established TCP connection. Connecting from scratch has four steps — name resolution, establishing TCP, the TLS handshake and the request itself — and the first two pay round trips of their own over the same link. They are not inside the measured 43.6 ms: the
connectcolumn in the run is a connection to the link on the same machine, 0.3 ms. - Per connection. Measured: the handshake took 43.6 ms against a 40 ms round trip, one round trip at setup. A client that keeps a connection and sends a hundred requests through it pays the handshake once out of a hundred — which is why "the first request is slow" is not an anomaly but exactly this price.
- It needs state on both sides: the client keeps a ticket, the server can accept it. A client with a new context per request loses the ticket; a load balancer hands the connection to a server that shares no ticket secret with the issuer, and it is not accepted. Both are visible only through the share of resumed handshakes, not through average time.
What is covered
- What this question is really about
- Base: what the two sides agree on, and what a connection is made of
- Mechanism 1: a handshake costs round trips
- Mechanism 2: resumption does not always save a round trip
- Mechanism 3: what resumption actually saves
- Mechanism 4: it is paid per connection, not per request
- Deeper: only 0-RTT removes the wait before data, and its price is stated
- How to answer in an interview
- Next they ask
- Common misconceptions
- Practice
- Knowledge check
Sources & further reading
2 SOURCES
- RFC 8446, The Transport Layer Security (TLS) Protocol Version 1.3Source. Where it is established that 0-RTT removes the wait before data is sent, and what is paid for it. That no other mode in TLS 1.3 saves a round trip is a conclusion from our own measurement, not a statement of the standard. From the list of differences against TLS 1.2: "A zero round-trip time (0-RTT) mode was added, saving a round trip at connection setup for some application data, at the cost of certain security properties". Which properties exactly is stated in the same document, in the section on 0-RTT: "This data is not forward secret, as it is encrypted solely under keys derived using the offered PSK" and "There are no guarantees of non-replay between connections".https://www.rfc-editor.org/rfc/rfc8446.html
- RFC 5246, The Transport Layer Security (TLS) Protocol Version 1.2Source. Where it is established that in TLS 1.2 the client sends its half of the key exchange only after the server has chosen — that is, where the extra round trip comes from: "The ClientKeyExchange message is now sent, and the content of that message will depend on the public key algorithm selected between the ClientHello and the ServerHello". And that the certificate is sent by the server: "Following the hello messages, the server will send its certificate in a Certificate message if it is to be authenticated".https://www.rfc-editor.org/rfc/rfc5246.html