UDP — User Datagram Protocol
Connectionless, unreliable, lightweight. The header, the checksum, and the cases where UDP is the right answer.
What it is#
UDP (User Datagram Protocol, RFC 768) is the simplest useful transport. It takes IP’s host-to-host datagrams, adds two port fields so the receiver can demultiplex by process, adds a length and a checksum, and stops. There is no connection, no handshake, no acknowledgement, no retransmission, no ordering, no flow control, no congestion control. Each datagram is independent — sender drops it on the wire and forgets it ever existed.
That sounds primitive, and it is. It’s also exactly right for a surprising number of workloads: DNS queries (one packet out, one packet back, retry at the application layer), NTP, real-time voice and video, multicast streaming, network telemetry, and the modern Internet’s biggest UDP user — QUIC, which builds the whole TCP-replacement stack on top of UDP datagrams.
The header is 8 bytes. The protocol fits comfortably on one page of the RFC.
When to use it#
Reach for UDP when any of these are true:
- Setup cost matters more than reliability. DNS lookups, NTP queries, service-discovery probes. A TCP handshake would cost more than the actual exchange.
- Late data is worse than lost data. Real-time audio/video — a packet that arrives 200 ms late is unplayable; better to drop it and conceal the gap.
- You want to multicast or broadcast. TCP cannot do either by definition. UDP supports both natively.
- You will build your own reliability anyway. QUIC, DTLS, game-engine net code, custom RPC frameworks all do this. UDP is the lowest-friction substrate.
- The application is short, idempotent, and retryable. DNS, SNMP, syslog, RADIUS, DHCP. Retry at the application layer; no per-connection bookkeeping.
Skip UDP when:
- You need reliable in-order delivery of a stream of bytes and you don’t want to reimplement TCP. Use TCP.
- Your traffic crosses firewalls and middleboxes that are UDP-hostile. Some enterprise networks drop UDP aggressively. QUIC adoption is partly a war against this.
- You can’t afford to think about congestion. UDP applications that ignore congestion can saturate links and starve TCP flows on the same path. If you ship a UDP protocol, you owe the network a congestion-response mechanism.
How it works#
The header#
8 bytes, four 16-bit fields:
0 1 2 3 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+| Source Port | Destination Port |+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+| Length | Checksum |+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+| Data |+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+- Source port — optional in UDP (may be zero if the sender doesn’t expect a reply). When present, it’s the port the receiver should reply to.
- Destination port — the receiving process’s port. Combined with the destination IP, this is what the kernel uses to demultiplex.
- Length — total length of the UDP datagram (header + data) in bytes. Minimum 8 (header only); maximum technically 65535 but practically limited by IP MTU.
- Checksum — covers the UDP header, data, and a pseudo-header from IP (source IP, dest IP, protocol, UDP length). Optional in IPv4 (zero means “not computed”); mandatory in IPv6.
That’s all. No sequence number, no ack number, no flags, no window.
Send and receive#
On the sender:
- Application calls
sendto(socket, data, len, addr). - Kernel wraps the data with a UDP header (fills in length and computes the checksum).
- Wraps that with an IP header (fills in source/dest IP, sets protocol = 17 for UDP).
- Hands it to the link layer; one packet on the wire.
On the receiver:
- NIC delivers the IP packet to the kernel.
- Kernel sees protocol = 17, strips the IP header, hands the UDP segment to the UDP layer.
- Kernel looks up the socket bound to
(dst IP, dst port), enqueues the data. - Application’s
recvfromreturns the data and the sender’s address.
No state on either side — the receiving socket doesn’t care which sender’s datagram comes next.
Datagram boundaries#
Unlike TCP, UDP preserves message boundaries. One sendto produces exactly one datagram, which becomes exactly one recvfrom on the receiver (if it arrives at all). The application never has to frame messages itself.
The price: a too-large datagram either fragments at IP (if DF is unset) or fails outright. Most applications size datagrams to fit a single MTU — about 1472 bytes of UDP payload on standard Ethernet, less on the Internet where the safe number is closer to 1200.
Variants#
- UDP-Lite (RFC 3828) — checksum covers only a chosen prefix. Useful for voice codecs that can tolerate payload bit-errors but not header corruption.
- DTLS — TLS over UDP. Used by WebRTC media channels and (formerly) some VPNs. Adapts TLS’s record-layer to datagram semantics — no in-order assumption, no stream cipher state across records.
- QUIC — IETF RFC 9000. Reliability, ordering, multiple streams, congestion control, integrated TLS 1.3, all on UDP. Carries HTTP/3. The most significant transport-layer change in 30 years; UDP is the substrate.
- Multicast UDP — datagrams to a group address. Used for IPTV, financial-market data feeds, service discovery (mDNS, SSDP).
- GeneVE / VXLAN — overlay-network encapsulations that carry layer-2 frames inside UDP. Foundation of modern cloud networking.
Trade-offs#
Other tensions:
- Application complexity. UDP pushes work into the application — retries, timeouts, framing of multi-datagram responses. TCP handles these in the kernel.
- Amplification risk. Some UDP services (DNS, NTP, memcached on UDP) reply with much more than they receive. Attackers spoof the source IP and use the service as an amplifier. Mitigation: response-rate limiting, source-IP validation, disabling UDP modes that aren’t needed.
- Path MTU. TCP’s MSS negotiation hides MTU concerns. UDP applications must size datagrams conservatively or risk fragmentation (often dropped by middleboxes).
- Observability. A UDP “flow” only exists by convention (same 5-tuple, close in time). Tools like
ssshow TCP sockets richly; UDP sockets are nearly stateless from the kernel’s view.
Why is the UDP checksum optional in IPv4 but mandatory in IPv6?
IPv4 has its own header checksum, which gives some end-to-end protection. IPv6 dropped the IP-layer checksum to make router forwarding cheaper — routers no longer recompute a checksum at every hop. With no IP checksum, the transport layer is the only line of defence against bit-flips, so IPv6 requires UDP applications to compute and check it.
Common pitfalls#
- Assuming delivery. Every UDP
sendtomay silently disappear. Build in retries with a sane backoff, especially across the Internet where loss rates are non-trivial. - Assuming order. Reordering is rare on a direct path but real across multipath networks. If order matters, add sequence numbers in the payload.
- Oversized datagrams. A 4 KB UDP datagram will fragment at IP. Some firewalls drop fragments. Keep payloads under the path MTU; for unknown paths, target 1200 bytes.
- Ignoring congestion. A tight UDP send loop with no pacing will saturate the upstream link and lose packets without you noticing. Tools like
iperf3 -uneed explicit bandwidth caps for a reason. - Trusting the source IP. UDP source addresses are trivially spoofable. Authenticate at the application layer (DTLS, message MACs) or use cookies for setup.
- Confusing “UDP is fast” with “UDP is right.” UDP is faster only because it does less. If your application ends up reimplementing TCP poorly on top of UDP, just use TCP.
- Not handling
EAGAINon receive. On non-blocking UDP sockets,recvfromreturnsEAGAINwhen no datagram is queued. Treat it as “try again later,” not as an error. - Forgetting the receive-buffer limit. The kernel drops UDP datagrams silently when the socket’s receive buffer overflows.
SO_RCVBUFtunes it;netstat -sushows the drop counter.
Related building blocks#