TCP vs UDP
TCP vs UDP
Every byte you send over the internet travels inside a transport-layer packet. Two protocols dominate this layer: TCP (Transmission Control Protocol) and UDP (User Datagram Protocol). Choosing the wrong one can tank the reliability of a banking service or double the latency of a live video game. Understanding the difference — not just the textbook definition, but the real engineering trade-offs — is essential for system design.
What Is TCP?
TCP is a connection-oriented, reliable, ordered, and error-checked protocol. Before a single byte of application data moves, TCP performs a three-way handshake:
- Client sends
SYN— "I want to connect." - Server replies
SYN-ACK— "Agreed, ready." - Client sends
ACK— "Connection established."
After that, every segment sent by one side is acknowledged (ACK) by the other. If an acknowledgment does not arrive within a timeout window, the sender retransmits. TCP also enforces in-order delivery: if segment 4 arrives before segment 3, TCP buffers it and only delivers both to the application once segment 3 arrives too. Finally, TCP's congestion control algorithms (Slow Start, AIMD) automatically throttle the send rate when the network is congested.
What Is UDP?
UDP is connectionless and unreliable. There is no handshake, no acknowledgment, no retransmission, and no ordering guarantee. A UDP sender fires a datagram into the network and immediately moves on. If the packet is dropped, corrupted, or arrives out of order, the protocol does nothing — it is entirely the application's responsibility to handle those cases (or ignore them).
This sounds like a liability, but it is also UDP's superpower. The absence of handshake and retransmission overhead makes UDP:
- Faster — no round-trip required before data flows.
- Lower latency — no queuing behind retransmitted segments.
- Lighter on the network stack — the UDP header is just 8 bytes vs. TCP's 20-60 bytes.
Side-by-Side Comparison
When to Use TCP
Use TCP whenever losing or reordering data would produce a corrupt or incorrect result:
- HTTP/HTTPS — a missing byte in an HTML page or JSON API response renders it broken.
- Databases over a network — a dropped byte in a SQL query or result set corrupts the operation.
- File transfers (FTP, S3 uploads) — a missing segment silently corrupts the file.
- Email (SMTP, IMAP) — emails must arrive intact.
- SSH / remote admin — a dropped character in a shell command has consequences.
Roughly speaking: if you would need to implement retransmission and ordering yourself in UDP, just use TCP instead.
When to Use UDP
Use UDP when timeliness beats completeness — a stale retransmitted packet is worse than no packet:
- Live video & audio streaming — a 200 ms-old video frame is useless; skip it and render the next one. WebRTC (used by Zoom, Google Meet) runs over UDP-based DTLS/SRTP.
- Online multiplayer games — player positions are sent dozens of times per second. A retransmit of a 50 ms-old position would arrive after the current position update anyway.
- DNS — a single-packet request/response that fits in one datagram; a TCP handshake would double the lookup time.
- DHCP — network bootstrapping before an IP address is even assigned.
- IoT sensor telemetry — a missed temperature reading is acceptable; low overhead on constrained devices matters.
- QUIC (HTTP/3) — Google's QUIC protocol runs over UDP so it can implement its own smarter, multiplexed reliability layer without the OS-level head-of-line blocking of TCP.
The Real Numbers: Latency Cost of TCP Handshake
Every new TCP connection pays a minimum of 1 RTT (round-trip time) before data can flow, plus another RTT for TLS if HTTPS is used (TLS 1.3 reduced this to 1 RTT). On a cross-continental link where RTT is ~100 ms, this means:
- TCP handshake alone: 100 ms
- TCP + TLS 1.3: 200 ms
- TCP + TLS 1.2 (older): 300 ms
- UDP (no handshake): 0 ms setup, first packet goes immediately
This is why connection pooling (reusing TCP connections) is so important in HTTP/1.1, and why HTTP/2 multiplexing and HTTP/3 (QUIC) eliminate the per-request connection cost entirely.
Hybrid Approach: UDP with Application-Level Reliability
Sophisticated systems sometimes choose UDP and then implement only the reliability they actually need. For example, a multiplayer game might:
- Send player positions over UDP — unreliable, unordered, accept drops.
- Send critical game events (player died, item picked up) over the same UDP socket but with a custom sequence number + selective ACK scheme — just enough reliability for game-state consistency.
This granular control is impossible with TCP, where you take all-or-nothing reliability for the entire stream.
Key Design Heuristics
- Default to TCP (via HTTP/2 or HTTP/3) for any service where data integrity matters.
- Choose UDP for real-time media, gaming, or DNS — where latency matters more than completeness.
- Consider QUIC/HTTP/3 when you need reliability but also care about head-of-line blocking and connection setup latency.
- Never let "UDP is faster" be the only reason to switch — measure the actual RTT and packet-loss rates in your environment first.