Skip to main content
Networking

TCP vs UDP for developers: when the protocol actually matters

TCP guarantees delivery and order; UDP doesn't. That tradeoff is well-known. The part that's less obvious is why some high-performance systems deliberately choose the unreliable option — and build reliability back in themselves.

Thien Nguyen
By Thien Nguyen
Updated July 20, 2026 · 4 min read

Most developers work at layers above TCP and UDP — they use HTTP, WebSockets, or gRPC, and the protocol choice is made for them. But occasionally you're building something low-level enough that it matters: a game server, a live video stream, a custom protocol over raw sockets, or something using QUIC. And the decision comes down to a tradeoff that's deeper than "reliability vs speed."

What TCP guarantees

TCP (Transmission Control Protocol) provides three guarantees on top of IP's best-effort delivery:

  • Reliability: every byte sent will arrive (or the connection will fail with an error — no silent drops).
  • Order: bytes arrive in the order they were sent, regardless of how IP packets were routed.
  • Flow and congestion control: TCP adjusts the send rate based on the receiver's buffer capacity and network conditions, avoiding sending more than the channel can handle.

These guarantees are implemented via acknowledgments (ACKs) and retransmission: the sender marks every segment and waits for the receiver to confirm receipt; unacknowledged segments are retransmitted after a timeout. The connection setup (the three-way handshake) and teardown also add round-trips, which is the overhead you hear about in latency-sensitive comparisons.

The most important TCP behavior for understanding performance is head-of-line blocking: if one packet is lost, TCP pauses delivery of all subsequent packets until the lost one is retransmitted and fills the gap in the byte stream. Even packets that arrived perfectly fine sit buffered, waiting. For applications where individual units of data are independent (game state updates, individual video frames), this is worse than just losing the packet — you get a stall.

What UDP provides

UDP (User Datagram Protocol) is a thin wrapper around IP. It adds source and destination ports, a length field, and an optional checksum — nothing else. No connection setup, no acknowledgment, no ordering, no congestion control. A UDP send is a fire-and-forget: you hand the datagram to the kernel and you don't know whether it arrived.

That sounds strictly worse, but it's a feature when:

  • Latency beats completeness: a live game state update from 50ms ago is worthless; it's better to drop it and deliver the current one. TCP would buffer and retransmit the stale state; UDP lets you ignore it.
  • You want to control retransmission yourself: a custom protocol knows which packets need reliability (game events: player picked up item) and which don't (player position updates every 16ms). TCP applies the same retransmission policy to both; UDP lets you differentiate.
  • You need low connection overhead: UDP has no handshake. For short-lived request/response patterns where a TCP handshake adds unacceptable latency (DNS queries are the canonical example), UDP's connectionless model wins.

Where this plays out in practice

Video and audio streaming: live streams are UDP-based (or UDP-derived). A dropped audio packet creates a brief glitch; retransmitting it 100ms later creates an unintelligible delay. The same applies to video conferencing — WebRTC uses UDP, accepts some packet loss, and uses codec-level concealment to hide the gaps.

DNS: queries are single round-trip UDP datagrams by default. If the response is too large for one datagram, DNS falls back to TCP for that query. The connection overhead of TCP for a simple name lookup would be disproportionate.

Gaming: game servers typically send world state on UDP at 20–60Hz. Each packet supersedes the previous one, so ordering and retransmission are the application's problem (or something they deliberately skip). Input events (shoot, jump, interact) often get their own reliability layer on top of UDP.

HTTP/3 and QUIC: the biggest recent shift. HTTP/2 solved head-of-line blocking at the HTTP layer but still had it at the TCP layer. QUIC runs on UDP and implements its own reliability, ordering (per-stream, not globally), and congestion control — giving you TCP-like guarantees without TCP-level head-of-line blocking. HTTP/3 is QUIC-based; as of 2025 it's supported by all major browsers and a growing fraction of servers.

The "just use TCP" rule of thumb

For most application development, the right call is TCP (through whatever library or protocol sits on top of it). The guarantees are correct for the vast majority of data: you want every HTTP response delivered in order, every database query result present and uncorrupted, every file transfer complete.

The exceptions are applications where you're explicitly reasoning about partial data being acceptable or where you need per-stream rather than global ordering guarantees. If you find yourself implementing your own ACK system on top of UDP, pause and ask whether QUIC or a library like KCP or ENet solves the problem at a level where the tradeoffs are already worked out.

Inspect real traffic

Our IP Lookup resolves hostnames, ASN data, and geolocation for any IP — useful when you're debugging where a UDP or TCP connection is actually routing and whether traffic is reaching the expected server infrastructure.

NetworkingProtocolsFundamentals

Related articles

All articles