TLS 1.3 vs TLS 1.2 in practice
TLS 1.3 has been stable since 2018. Almost everything supports it now. Almost. Some practical notes from migrating internal services off TLS 1.2 over the past year.
The handshake is shorter. TLS 1.2 needs two round-trips before the first application byte. TLS 1.3 needs one. On the public internet this is a ~80ms latency win per cold connection; on the LAN it’s noise. If your service is mostly long-lived connections (postgres, redis, internal gRPC), the win doesn’t show up.
The cipher list is shorter and saner. TLS 1.3 dropped CBC, dropped RSA key exchange, dropped renegotiation. The remaining suites are all AEAD (AES-GCM, ChaCha20-Poly1305) and all forward-secret. The practical effect is that the typical “what ciphers should I configure?” question becomes “use the defaults.”
0-RTT is a footgun. If your server accepts 0-RTT (early data), clients can replay requests. For idempotent GETs that’s fine. For anything with side effects (POST, PUT, DELETE), it’s a problem. Most stacks disable 0-RTT by default; double-check yours.
Cert algorithm matters slightly. ECDSA P-256 keys produce ~32-byte signatures; RSA-2048 produces 256-byte. On a low-RTT link the difference is invisible. On a 200ms RTT mobile link with TLS 1.2 (two RTT), shaving ~500 bytes off the handshake is barely a percentage point. With TLS 1.3 (one RTT, smaller ServerHello), it’s noise. Use ECDSA because it’s a smaller cert; don’t use it because you think it’ll be visibly faster.
The migration story: turn off TLS 1.2 server-side once your client fleet supports 1.3. For the public internet that’s “now.” For embedded devices that’s “we’ll see.”