TCP vs UDP vs QUIC
Published
TCP is a registered post parcel. Every piece is numbered, the receiver confirms what arrived, anything lost is sent again, and the pieces are handed over in order. UDP is throwing leaflets from a moving car. Each leaflet goes on its own, some never land, some land out of order, and nobody keeps track. QUIC is a courier company that took the leaflet truck and built its own tracking system on top, so it gets the reliability of the parcel service without the parcel service's slow paperwork.
All three sit at the transport layer, between IP (which only moves packets from one machine to another, with no promises) and your application.
You are building a multiplayer cricket game where each phone sends the batsman's position 30 times a second. A packet is lost. Should the protocol stop and resend it before delivering newer positions? Which transport would you pick?
TCP: reliable, ordered, careful#
TCP gives your application a byte stream: what you write on one end comes out the other end complete and in order, or the connection fails. To do that it:
- Opens a connection with a three way handshake (SYN, SYN-ACK, ACK) before any data.
- Numbers every byte, has the receiver acknowledge them, and retransmits what is not acknowledged.
- Hands bytes to the application strictly in order. If packet 5 is lost, packets 6 to 50 wait in a buffer until 5 arrives.
- Runs flow control (do not overwhelm the receiver) and congestion control (do not overwhelm the network), slowing down when it sees loss.
That is exactly what you want for a web page, an API response, a file or a database query, where a missing byte means a corrupt result. It is the transport under HTTP/1.1 and HTTP/2, SSH, SMTP, PostgreSQL and MySQL.
UDP: send and forget#
UDP adds almost nothing to IP: port numbers and a checksum, an 8 byte header. No handshake, no acknowledgements, no ordering, no retransmission, no congestion control. Each datagram is on its own.
That sounds bad until you meet data that is worthless once it is late. A video call frame from 200 ms ago, a player's position from three updates back, a sensor reading that has been superseded: resending them wastes time on data nobody wants. UDP lets the application decide what is worth recovering. DNS uses it because a query and its answer each fit in one packet and the client can simply ask again. Video calls (WebRTC in Google Meet and WhatsApp calls), online games, VoIP and live streaming protocols build on it.
QUIC: TCP's guarantees, rebuilt on UDP#
TCP is implemented in operating system kernels and in every router and middlebox on the internet, which makes it nearly impossible to change. Google started QUIC around 2012 to get around that by building a new transport on top of UDP, in user space, where it can evolve with an app update. The IETF standardised it in 2021 (RFC 9000), and HTTP/3 runs on it.
What it changes:
- TLS 1.3 is built in. The transport handshake and the encryption handshake happen together, so a new connection costs one round trip instead of two. A returning client can send data in its very first packet (0-RTT).
- Independent streams. One connection carries many streams, and a lost packet only stalls the stream it belonged to. TCP would stall all of them. This is head of line blocking, and it is shown step by step in HTTP/1.1 vs HTTP/2 vs HTTP/3.
- Connection migration. A TCP connection is identified by four values: two IPs and two ports. Walk out of your office WiFi onto 4G and your IP changes, so every TCP connection dies. QUIC identifies connections by a connection ID, so it carries on.
- Encrypted headers. Middleboxes cannot read or tamper with most of the transport, which is also why some corporate firewalls block it and browsers fall back to TCP.
Handshake round trips matter most where round trips are long, which is a lot of the world: a phone on a congested mobile network, or a user in India talking to a server in the US.
Mumbai to US East is around 200 ms. Each round trip removed is something every first visit feels. This, more than throughput, is why Google moved its traffic to QUIC.
| Choice | What you gain | What you pay | Pick it when |
|---|---|---|---|
| TCP | Reliable, ordered, universally supported, every tool understands it. | Handshake round trips, head of line blocking, connections die when the IP changes. | Default for request and response: APIs, databases, file transfer, anything internal. |
| UDP | No handshake, no waiting on lost packets, the application decides what to recover. | You build any reliability, ordering and congestion control you need yourself. Some networks block it. | Real time media, games, DNS, telemetry where fresh beats complete. |
| QUIC | 1-RTT and 0-RTT handshakes, encryption built in, independent streams, survives network changes. | More CPU than kernel TCP, newer tooling, sometimes blocked by firewalls (so keep a TCP fallback). | Public facing HTTP to mobile and far away users: HTTP/3. |
- PostgreSQLTCP: databases need every byte, in order
- WhatsAppUDP: voice and video calls via WebRTC
- ChromeQUIC: HTTP/3 to Google, YouTube and others
- CloudflareServes HTTP/3 over QUIC at the edge
In the interview#
Checkpoint#
1. A packet of position data is lost in a 30 updates a second game. What is the best behaviour?
2. What is head of line blocking in TCP?
3. Why does a QUIC connection survive switching from WiFi to mobile data?
- TCP: reliable, ordered byte stream. Handshake, acks, retransmits, congestion control.
- UDP: 8 byte header, no promises. For data that is worthless when late.
- QUIC: on UDP, TLS 1.3 built in, 1-RTT (0-RTT on resume), per stream ordering, connection migration.
- HTTP/3 = HTTP over QUIC. Keep a TCP fallback.
- 0-RTT data can be replayed. Only for idempotent requests.
TCP gives an application a reliable, ordered byte stream: a three way handshake, acknowledgements, retransmission, and flow and congestion control. That is right for APIs, databases and files, but a lost packet blocks everything behind it, and a new connection with TLS costs two round trips. UDP is an eight byte header on IP with no promises at all, which suits data that is worthless when late: voice and video calls, games and DNS, where the application decides what to recover. QUIC rebuilds reliable transport on top of UDP in user space: TLS 1.3 is part of the handshake, so new connections take one round trip and resumed ones zero, each stream is ordered independently so loss only stalls one stream, and connections survive IP changes through a connection ID. HTTP/3 runs on QUIC. I use TCP inside the data centre, UDP for real time media, and QUIC for public HTTP to mobile and distant users, with a TCP fallback.