Skip to main content
networking

TCP vs UDP

12 min read
Fully authored

Reliable-ordered vs fire-and-forget — and when you want the second.

In 1974, Vint Cerf and Bob Kahn published a paper titled "A Protocol for Packet Network Intercommunication." It described a single unified protocol they called TCP — Transmission Control Protocol. The idea: a computer sends a stream of bytes to another computer, and the protocol guarantees they arrive in order, with no duplicates, no missing bytes, and no corruption. If a packet is dropped by the network, TCP retransmits it. If two packets arrive out of order, TCP reorders them. If a network is congested, TCP slows down.

Six years later, in 1980, Jon Postel wrote RFC 768 — a 3-page specification for a different protocol called UDP — User Datagram Protocol. UDP does exactly one thing: sends a packet from one process to another. No retransmit. No ordering. No congestion control. No connection. If a packet is dropped, it's gone. If two packets arrive out of order, tough. UDP is 8 bytes of header wrapped around your data.

Why would anyone use UDP? Because for some workloads, reliability costs more than it's worth. Video streaming: a dropped frame from 2 seconds ago is worse than useless — it's stale. Online gaming: a re-sent "player position" from 100ms ago is nonsense. DNS: a single UDP packet is faster than 3 round trips of TCP handshake for a 40-byte query. When latency matters more than reliability, UDP wins. When reliability matters more than latency, TCP wins.

The papers

  • Cerf & Kahn (1974) — "A Protocol for Packet Network Intercommunication." The paper that won them the Turing Award in 2004.
  • RFC 793 (1981) — the definitive TCP specification.
  • RFC 768 (1980, Postel) — the entire UDP specification. 3 pages.
  • RFC 9000 (2021) — QUIC. A new UDP-based transport that combines TCP's reliability with UDP's speed. Powers HTTP/3.

What layer? Both are Layer 4

TCP and UDP are both Layer 4 (Transport) protocols in the OSI model. They sit above IP (Layer 3) and below the application (Layer 7). Their job is the same: get data from a process on one host to a process on another host. They just do it differently.

Where TCP and UDP live
L7 · Application (HTTP, DNS, SSH, gRPC…)
L4 · TCP
Reliable + ordered · handshake · retransmit · congestion control
L4 · UDP
Fire-and-forget · no state · no retransmit · low overhead
L3 · IP (addressing + routing)
Applications pick TCP or UDP based on what the workload needs. The choice is baked into the protocol: HTTP always TCP (until HTTP/3), DNS mostly UDP, video calls UDP, databases TCP.

The TCP 3-way handshake — how a connection starts

Every TCP connection begins with a 3-way handshake. This is why the very first packet of an HTTP/1.1 or HTTP/2 request has ~1 round-trip of latency before any real data flows.

TCP 3-way handshake — step 1 of 5
SYN → SYN-ACK → ACK, then data.
ClientServerCLOSEDLISTEN
Starting state — server is LISTEN (accept()ing on a port). Client wants to connect.

The handshake exchanges initial sequence numbers (ISNs) so both sides can track what's been sent, received, and needs retransmit. It also lets each side confirm the other is reachable and willing to talk. The cost: 1 RTT of latency before your HTTP GET even leaves the client. On transatlantic links (~80ms RTT), that's 80ms of overheadper connection. This is why HTTP/1.1 introduced keep-alive (reuse connections), why HTTP/2 multiplexes many streams per connection, and why HTTP/3 moved to UDP-based QUIC (which combines handshake with TLS handshake for 0-RTT).

TCP reliability — how it works

TCP provides reliable, ordered, exactly-once byte delivery over an inherently unreliable network. Four mechanisms make this work:

  • Sequence numbers — every byte has a unique 32-bit sequence number. Receiver can detect gaps and duplicates.
  • Acknowledgments (ACKs) — receiver periodically sends back "I've got everything up to byte N." Sender retransmits anything not ACKed within a timeout (RTO — Retransmission Timeout).
  • Sliding window flow control — receiver tells sender "I have room for the next 64 KB right now." Sender never overwhelms receiver.
  • Congestion control — sender starts slow, ramps up until packet loss is detected, then backs off. CUBIC (Linux default 2004+) and BBR (Google, 2016+) are the modern algorithms.
Interactive: simulate packet loss on TCP vs UDP
Delivered
0 / 10
Retransmitted
0
Extra latency
+0ms
TCP delivers all 10 packets no matter what — but retransmits 0 of them, each adding ~100ms of latency (RTO timeout). This is why high-loss networks make TCP feel slow.

UDP — everything TCP is not

UDP has none of TCP's mechanisms. No handshake. No sequence numbers. No ACKs. No retransmit. No flow control. No congestion control. Just 8 bytes of header (source port, destination port, length, checksum) around your data. You send a UDP packet; it arrives, or it doesn't. The kernel doesn't track it. There's no connection state.

UDP's minimalism is its power. A UDP packet has no setup cost — first byte can be application data. UDP has no head-of-line blocking — if packet 47 is dropped, packet 48 is still delivered immediately. UDP has no congestion control — but modern UDP-based protocols (QUIC, WebRTC) implement their own, smarter than TCP's.

Side by side — the head-to-head

DimensionTCPUDP
Connection setup3-way handshake (SYN → SYN-ACK → ACK)None — first packet is data
Header size20 bytes (min), can go to 60 with options8 bytes
ReliabilityGuaranteed — retransmits lost packetsNone — dropped packets are lost forever
OrderingGuaranteed — receiver reorders packetsNone — packets arrive in any order
Duplicate detectionYes (sequence numbers)None
Flow controlYes (sliding window)None
Congestion controlYes (CUBIC, BBR, Reno, …)None (but QUIC adds its own)
Head-of-line blocking?Yes — one lost packet stalls the streamNo — every packet independent
Latency (steady state)1 RTT setup + per-packet ~RTT0 setup + per-packet ~RTT
Latency (packet loss)Adds ~1 RTO (~100-500ms)No penalty (packet just gone)
State per connectionSequence, window, RTT, congestion stateNone
UsesHTTP/1.1, HTTP/2, SSH, SMTP, databases, file transferDNS, video streaming, VoIP, gaming, NTP, SNMP, QUIC

When to pick each — a real-world guide

TCPLoading a web page
HTML/CSS/JS must arrive complete and in order. No dropped bytes. Missing a script breaks the page.
TCPSSH into a server
You cannot lose bytes in a shell session. Reliability > latency.
TCPDatabase queries
Query and result set must be complete and ordered. Corruption unacceptable.
UDPLive video calls (Zoom, Meet)
A frame 500ms old is worthless. Better to drop it and show the next frame. UDP has no retry overhead.
UDPOnline gaming (Fortnite)
Player positions update 60x/second. A stale position from 200ms ago would ghost your character. Skip it, use the next one.
UDPDNS lookups
50-byte query, 50-byte response. TCP handshake would triple the latency of a simple name resolution.
UDPMetrics + logs
If one datapoint is dropped, the next arrives in 15s. Overhead of TCP not worth it.
QUICHTTP/3
Combines TCP's reliability + UDP's no-HoL blocking + integrated TLS in a single packet. Modern web transport.

QUIC — the third option (2021)

For 40 years the choice was binary: TCP or UDP. In 2021, Google shipped QUIC (Quick UDP Internet Connections, RFC 9000) — a new transport protocol built on UDP that gives you TCP's reliability + ordering + flow control plus UDP's absence of head-of-line blocking, 0-RTT connection setup, and integrated TLS 1.3.

QUIC lives in userspace, not the kernel — so it can be updated faster (Google ships QUIC changes weekly to Chrome). QUIC streams are independent — if one stream stalls, others keep flowing. QUIC survives IP changes (your phone switches from WiFi to LTE, QUIC keeps the connection going via a connection ID). HTTP/3 runs entirely on QUIC.

Applied in real systems — a lot of examples

The choice between TCP and UDP shows up in every system design. Here's a wide sample of real-world usage.

HTTP/1.1, HTTP/2
Deep dive

HTTP → TCP

Every HTTP/1.1 and HTTP/2 request runs on TCP. Reliability is essential — you can't have missing bytes in an HTML page. Ordering is essential — bytes must arrive in order. This is why HTTP has always been TCP. Until HTTP/3.

Read the deep dive →
HTTP/3
Deep dive

HTTP/3 → QUIC (on UDP)

HTTP/3 abandoned TCP. It runs on QUIC, which runs on UDP. This solves TCP head-of-line blocking: with HTTP/2 on TCP, one dropped packet stalls every stream. With HTTP/3 on QUIC, only the affected stream stalls.

Read the deep dive →
Netflix video streaming
Deep dive

Netflix → TCP (HLS/DASH over HTTPS)

Surprising: Netflix streams video over TCP, not UDP. Because it's not live (it's pre-encoded), you can afford small pauses to retransmit. Netflix uses Adaptive Bitrate over HTTPS chunks. Netflix Open Connect serves this at the ISP edge.

Read the deep dive →
Zoom video calls
Deep dive

Zoom → UDP (RTP over UDP)

Real-time video is UDP. Zoom uses SRTP (Secure Real-Time Protocol) over UDP for the audio/video. Dropped frames are tolerated (video briefly glitches, audio has a click) — but retransmit would be worse (out-of-sync audio and video).

Read the deep dive →
DNS queries
Deep dive

DNS → UDP (mostly)

DNS queries fit in a single ~50-byte UDP packet. Response in another. Round-trip: 1. TCP would need 3 round-trips (handshake + query). That's why DNS defaults to UDP. DNS uses TCP only for large responses (>512 bytes) or zone transfers.

Read the deep dive →
DNS over HTTPS/TLS
Deep dive

DNS over HTTPS (2018) → TCP

DoH (RFC 8484) runs DNS queries over HTTPS on TCP for privacy (ISPs can't spy). Cloudflare 1.1.1.1 and Google 8.8.8.8 both offer DoH. Trades DNS's traditional UDP speed for privacy.

Read the deep dive →
Online games
Deep dive

Fortnite, LoL, CS:GO → UDP

Every competitive online game uses UDP. Player positions update 60x per second. Missing one update is fine (interpolate). Retransmitting a stale one is worse than useless. Games implement their own lightweight reliability layer on top of UDP for critical events (kills, chat messages).

Read the deep dive →
Postgres, MySQL
Deep dive

Databases → TCP

Every SQL query hits the database over TCP. The queries and responses must be reliable and ordered — you can't tolerate a corrupted or reordered result set. Port 5432 (Postgres), 3306 (MySQL), 27017 (MongoDB). Some newer stores (Aerospike, ScyllaDB) offer UDP for reads with in-app retry.

Read the deep dive →
SSH
Deep dive

SSH → TCP

Every SSH connection is TCP on port 22. Missing bytes in a shell session would be catastrophic. Newer Mosh uses UDP for lower-latency mobile connections (survives IP changes) with a smart resync layer on top.

Read the deep dive →
Kafka
Deep dive

Kafka producers/consumers → TCP

Every Kafka client-broker connection is TCP. Kafka's at-least-once and exactly-once semantics are only possible because TCP guarantees byte delivery. Broker replication is also TCP.

Read the deep dive →
WebRTC
Deep dive

WebRTC media → UDP (SRTP)

WebRTC (Chrome, Meet, browser video calling) uses UDP for media. Data channels can use either. WebRTC negotiates via ICE/STUN/TURN to find working UDP paths through NATs.

Read the deep dive →
Google (everything)
Deep dive

Google services → QUIC (UDP-based)

Google migrated the majority of their client traffic to QUIC starting in 2013 (it was called gQUIC internally before IETF standardized it in 2021). YouTube, Search, Maps, Gmail all prefer QUIC when the client supports it. ~40% of internet traffic today is QUIC.

Read the deep dive →
Time synchronization
Deep dive

NTP → UDP

NTP (Network Time Protocol) uses UDP because clock sync must be sub-millisecond precise — TCP's handshake would introduce more error than the sync itself is trying to correct.

Read the deep dive →
Monitoring
Deep dive

SNMP, syslog → UDP

Network monitoring uses UDP because reliability is not worth the overhead — if a monitoring metric is dropped, the next one arrives in 15 seconds. Datadog agent, Prometheus node_exporter, and syslog all default to UDP.

Read the deep dive →

Key takeaways

  • Both are Layer 4 (Transport). TCP and UDP both sit above IP and below your application. Ports are their addressing scheme.
  • TCP = reliable, ordered, connection-oriented. 3-way handshake, sequence numbers, ACKs, retransmit, congestion control. Adds ~40 bytes header + 1 RTT setup.
  • UDP = fire-and-forget, connectionless. 8 bytes header, no setup. Packet delivered or not — no promises.
  • Pick TCP when reliability > latency: HTTP, databases, SSH, file transfer, email. Pick UDP when latency > reliability: real-time video, gaming, DNS, NTP.
  • QUIC (2021) is a third option — reliability + speed by running on UDP with its own smarter reliability layer. HTTP/3 uses QUIC. ~40% of internet traffic now.
  • Head-of-line blocking is TCP's Achilles heel: one dropped packet stalls every subsequent packet on that connection. QUIC / HTTP/3 solved this.
  • TCP is slower to start (handshake) and slower under packet loss (retransmit + window shrinking). UDP has no such overhead.

References

  • Cerf & Kahn (1974) — A Protocol for Packet Network Intercommunication. IEEE.
  • RFC 793 (1981) — TCP specification.
  • RFC 768 (1980) — UDP specification. 3 pages.
  • Jacobson (1988) — "Congestion Avoidance and Control." The paper that made TCP work under congestion.
  • RFC 9000 (2021) — QUIC v1 specification.
  • Cardwell et al. (2016) — "BBR: Congestion-Based Congestion Control." Google's modern TCP congestion algorithm.

Practice what you just read

Every foundation concept has a companion quiz to close the loop.