UDP — The Minimal Transport
Topic 25

UDP — The Minimal Transport

UDP

UDP is what you get when you add the bare minimum to IP and stop. It contributes two things the network layer lacks — port numbers for multiplexing and an optional checksum for corruption detection — and nothing more. No connection, no handshake, no ordering, no retransmission, no congestion control. A UDP send is one system call that drops a datagram on the wire and returns; whether it arrives is the network's problem, and recovering from loss is yours.

That minimalism is the feature, not a shortcoming. For DNS, where a query and reply each fit in one packet, opening a TCP connection would triple the round trips for nothing. For voice and video, a packet that arrives 200 ms late is useless and retransmitting it only makes the stream stutter worse. UDP is the right transport whenever a late packet is worse than a lost one — and the wrong one whenever you actually need every byte, in order, intact.

UDPminimal · fast
8-byte header, connectionless, message boundaries preserved. No handshake, no ordering, no retransmit — one send drops a datagram and returns. Wins when a late packet is worse than a lost one: DNS, VoIP, QUIC.
TCPreliable · ordered
20-byte header, connection-oriented, an ordered byte stream. Pays a handshake plus sequence numbers, ACKs, and retransmission for guaranteed, in-order delivery. Wins when every byte must arrive intact: files, APIs.

The UDP Header

The entire UDP header is eight bytes: source port, destination port, length, and checksum, each a 16-bit field. Compare that to TCP's 20-byte minimum header with its sequence numbers, acknowledgment numbers, window, and flags. The ports give the kernel its demultiplexing key; the length covers the header plus payload; the checksum, computed over a pseudo-header that includes the IP addresses, catches corruption end to end.

On IPv4 the checksum is technically optional — a sender may write zero to skip it — but on IPv6 it is mandatory, because IPv6 dropped the IP-layer header checksum and UDP is the only thing left guarding the payload. There is no sequence number and no acknowledgment field anywhere in those eight bytes, which is the whole point: there is no per-connection state to carry, so there is nothing to put in a header to track it.

Connectionless Semantics

UDP is connectionless: there is no handshake to set up and no teardown to wait out. The kernel holds no per-flow state for a UDP socket the way it does for a TCP connection — a server can receive datagrams from ten thousand distinct clients on one socket and the OS keeps no table of them. Each recvfrom() tells you the source address of that one datagram, and that is all the context you get.

UDP also preserves message boundaries, which TCP does not. If a client sends a 200-byte datagram and a 50-byte datagram, the receiver reads exactly 200 bytes then exactly 50 — one datagram per read, never merged or split. A TCP receiver, by contrast, sees an undelimited byte stream and must frame messages itself. For request/reply protocols where each message is self-contained, that boundary preservation removes a whole layer of framing logic.

Where UDP Wins

UDP owns the workloads where setup cost or retransmission latency dominates. DNS resolves a name in a single query/reply that usually fits one packet. DHCP bootstraps a host before it even has an address, so a stateful connection is impossible. VoIP and RTP stream real-time media where a missed sample is simply skipped, never resent. Online games push position updates dozens of times a second and only the latest one matters.

The most consequential modern user is QUIC, the transport under HTTP/3. QUIC deliberately built reliability, ordering, and congestion control on top of UDP rather than TCP — partly to escape TCP's head-of-line blocking, partly because UDP rides through the existing internet of NATs and middleboxes unmolested, and partly because a userspace stack on UDP can evolve without waiting for every kernel on earth to upgrade.

# a single DNS lookup is one UDP datagram out, one back
dig +short example.com
# watch it on the wire — no SYN, no handshake, just two packets
tcpdump -n -i eth0 udp port 53
# 10.0.0.5.51720 > 1.1.1.1.53: A? example.com   (query)
# 1.1.1.1.53 > 10.0.0.5.51720: A 93.184.216.34   (reply)

What You Must Build Yourself

Everything TCP gives you for free becomes your job over UDP. If your application cannot tolerate loss, you implement sequence numbers, acknowledgments, and retransmission yourself. If it cannot tolerate reordering, you buffer and resequence. And critically, if it sends sustained traffic, you must add congestion control — a UDP flow that blasts at line rate with no backoff is antisocial, starving every TCP flow sharing the link and worsening the congestion for everyone.

Most teams should not reimplement TCP badly on top of UDP. The honest default is to use QUIC or an existing reliable-UDP library when you need reliability, and reserve raw UDP for the cases where you genuinely want send-and-forget. Reaching for UDP to "go faster" and then bolting on a hand-rolled ACK scheme usually produces something slower and less fair than TCP would have been.

UDP vs TCP

UDP gives you ports, a checksum, message boundaries, and speed — no connection, no ordering, no retransmission, no congestion control. Choose it when a late packet is useless: DNS, DHCP, real-time voice and video, telemetry where only the freshest sample matters.

TCP gives you a reliable, ordered byte stream at the cost of handshake latency, head-of-line blocking, and per-connection state. Choose it whenever every byte must arrive in order — file transfer, HTTP/1 and HTTP/2, database protocols — which is the large majority of application traffic.

Common Mistakes
  • Sending sustained UDP with no application-level congestion control. A flow that never backs off starves the TCP traffic sharing the link and amplifies congestion — the network-abuse pattern that gets a service rate-limited or blocked.
  • Assuming UDP datagrams cannot be dropped or reordered. They can, exactly as IP packets can; code that treats every recvfrom() as guaranteed and in-order breaks the first time a packet is lost or arrives late.
  • Sending datagrams larger than the path MTU. An oversized UDP message fragments at the IP layer, and losing any single fragment discards the entire datagram — so a 4 KB datagram on a 1500-byte path is far more loss-prone than its size suggests.
  • Treating UDP as a reliable transport with a thin wrapper. Bolting a naive stop-and-wait ACK onto UDP usually yields worse throughput and worse fairness than TCP, since TCP's pipelining and congestion control took decades to tune.
  • Forgetting the checksum is mandatory on IPv6. Code ported from IPv4 that relied on a zero checksum sends datagrams an IPv6 stack will drop, because IPv6 has no IP-layer checksum to fall back on.
Best Practices
  • Pick UDP only when a late packet is worse than a lost one — real-time media, single-shot queries, freshest-sample telemetry — and reach for TCP whenever in-order completeness matters.
  • Keep datagrams under the path MTU, around 1400 bytes after headers, so a message rides in one packet and a single loss never wipes out a multi-fragment datagram.
  • Adopt QUIC or a maintained reliable-UDP library when you need reliability over UDP, instead of hand-rolling sequence numbers and retransmission that will be slower and less fair.
  • Add congestion response to any sustained UDP sender — pace output and back off on loss — so the flow coexists with TCP rather than starving it.
  • Design the protocol to tolerate loss, duplication, and reordering from the start, since UDP guarantees none of them and the app is the only layer that can recover them.
Comparable conceptsQUIC (reliability over UDP)SCTP (message-oriented transport)

Knowledge Check

For a VoIP call, why is UDP usually the right transport instead of TCP?

  • A retransmitted late audio sample is useless, so dropping it beats TCP's recovery
  • UDP's stronger checksum actually reconstructs the corrupted audio samples that a stricter TCP would simply discard
  • UDP guarantees lower jitter because its built-in congestion control paces the stream
  • UDP encrypts each datagram automatically, which TCP cannot do for media

An application sends 4 KB UDP datagrams over a path with a 1500-byte MTU and sees high message loss. Why?

  • The oversized 4 KB datagrams repeatedly overflow UDP's deliberately small receive window and are silently dropped at the receiver
  • Each datagram fragments into several IP packets, and one lost fragment drops it
  • UDP retransmits each datagram a fixed number of times, then gives up and reports loss
  • The 16-bit checksum cannot cover 4 KB, so oversized datagrams fail validation

Why did QUIC build its reliable transport on top of UDP rather than on TCP?

  • Because UDP moves bytes through routers faster than TCP at the hardware level
  • Because UDP already provides ordering and retransmission that QUIC could inherit directly
  • Because UDP crosses middleboxes and a userspace stack can evolve without kernel changes
  • Because UDP's own built-in congestion control turned out to be more advanced than TCP's, so QUIC simply reused it wholesale

You got correct