TCP vs UDP: What Breaks When You Pick Wrong
Head-of-line blocking, silent packet loss, Nagle delays -- the exact failure modes that show up when you choose the wrong transport.
Most “TCP vs UDP” explanations stop at a feature table: TCP is reliable and ordered, UDP is fast and connectionless. True, and useless. You don’t feel the difference until a wrong choice ships and something behaves in a way the table never warned you about — a multiplayer game that stutters precisely when the network is busiest, a metrics agent that reports numbers from 90 seconds ago, a file transfer that arrives corrupted with no error logged anywhere.
The useful way to learn the two protocols is backwards: pick each one for the wrong job and watch what breaks. The failure modes are specific, repeatable, and they map directly onto the guarantees each protocol makes.
What TCP guarantees, and what those guarantees cost
TCP gives you a byte stream that arrives in order, with no gaps and no duplicates, or the connection dies trying. To deliver that, it opens with a three-way handshake (SYN, SYN-ACK, ACK), assigns every byte a sequence number, acknowledges what it receives, retransmits what it doesn’t, and slows itself down when the network signals congestion. You write send(), the bytes come out the other end in the right order. That contract is why HTTP, SSH, and database wire protocols all sit on top of it.
The cost is hidden in the word ordered. TCP will not hand your application byte 5,000 until bytes 1 through 4,999 have arrived. If a single packet in the middle is lost, every packet that arrived after it sits in the kernel’s receive buffer, complete and useless, until the retransmission of the missing one lands. This is head-of-line blocking, and it is the single most important TCP behavior nobody mentions in the feature table.
Now pick TCP for a 60-tick multiplayer shooter. Each tick you send a position update. A packet drops — normal on any real network. TCP detects the loss and retransmits, which on a typical link takes at least one round-trip time, often more once the retransmission timer is involved. For that entire window, every newer position update is stuck behind the lost one. The player freezes, then snaps forward when the backlog flushes. The cruel part: this gets worse under load, exactly when players notice. You picked the protocol that prioritizes delivering stale data over delivering fresh data, in a domain where stale data is worthless.
There’s a quieter TCP trap too: Nagle’s algorithm. To avoid flooding the network with tiny packets, TCP may hold a small write, waiting to coalesce it with the next one. Combined with delayed ACKs on the receiver, this can stall a small request-response exchange for up to roughly 40 ms while each side waits for the other. For a chatty protocol sending many small messages, that latency is invisible in a LAN test and brutal in production. The fix is TCP_NODELAY, but you only reach for it once you know the behavior exists.
Where UDP wins, and the bill it hands you
UDP is almost nothing: a 8-byte header, source and destination ports, length, checksum. No handshake, no sequence numbers, no acknowledgments, no retransmission, no ordering, no congestion control. You hand the kernel a datagram and it tries once. The datagram arrives intact, arrives corrupted-and-discarded, arrives out of order relative to its siblings, arrives duplicated, or never arrives — and UDP tells you nothing about which happened.
That sounds worse, until you remember the game. With UDP, a lost position update is simply skipped; the next datagram carries a newer position anyway, so there’s nothing worth retransmitting. No head-of-line blocking, because there is no line. This is why real-time voice, video, and games live on UDP, and why QUIC — the transport under HTTP/3 — was built on UDP specifically to escape TCP’s head-of-line blocking while rebuilding reliability per-stream.
But UDP hands you a bill, and developers underpay it constantly. Pick UDP for a job that actually needs reliability — say, shipping log lines to a collector — and you will reinvent TCP, badly. First you notice lines go missing under load, so you add acknowledgments. Then duplicates appear, so you add sequence numbers to dedupe. Then you discover messages arrive out of order, so you add a reordering buffer. Then the receiver gets overwhelmed because nothing throttles the sender, so you add flow control. You have now written a worse TCP, with more bugs, and you still don’t have congestion control, so your agent contributes to network collapse during an incident.
There’s also a size trap. A UDP datagram larger than the path MTU (commonly around 1500 bytes on Ethernet) gets fragmented at the IP layer. If any single fragment is lost, the entire datagram is discarded — and many middleboxes drop IP fragments outright. So a 4 KB UDP message can vanish on networks where a 1 KB one always works, with nothing in your logs. Keeping datagrams under the MTU is a constraint you have to enforce yourself.
The decision, framed by failure mode
Skip the feature checklist. Ask one question: when a packet is lost, what does your application want to happen?
If the answer is “wait for it, I need every byte in order” — file transfer, an API call, a database query, anything where a gap corrupts meaning — use TCP and accept the latency variance. If the answer is “skip it, the next one supersedes it” — live telemetry, game state, voice, anything where freshness beats completeness — use UDP and budget engineering time for the reliability you do need.
| Failure mode | TCP | UDP |
|---|---|---|
| Packet lost mid-stream | Retransmits; later data blocks until it arrives | Skipped; next datagram proceeds independently |
| Out-of-order arrival | Reassembled in order for you | Delivered as-is; you reorder if you care |
| Receiver overwhelmed | Flow + congestion control throttle the sender | Nothing throttles; you build it or melt the link |
| Message exceeds MTU | Segmented transparently | IP-fragmented; one lost fragment drops the whole message |
The trap on both sides is the same shape: each protocol’s strength is the other’s failure mode. TCP’s ordering becomes head-of-line blocking. UDP’s leanness becomes a pile of reliability code you have to write and test yourself. Picking well means knowing which failure your application can tolerate, not which feature list looks longer.
Cursor
Socket bugs hide in the gap between what the protocol guarantees and what you assumed. An AI-native editor that reads your whole networking layer helps catch the mismatches — a UDP path that assumes ordering, a TCP write that needs TCP_NODELAY — before they ship.
Free tier; Pro at $20/mo
Affiliate link · We earn a commission at no cost to you.
FAQ
Is UDP always faster than TCP?
Why does HTTP/3 use UDP if UDP is unreliable?
Can I just use TCP everywhere and add TCP_NODELAY to fix latency?
The protocols haven’t changed in decades. What changes is whether you chose the one whose failure mode your application can actually absorb.
Related tools
Some links above are affiliate links. We may earn a commission if you sign up. See our disclosure for details.
Related reading
2026-09-02
The Best Monitors for Programming: PPI Over Size
A 27-inch 4K panel is 163 PPI; 1440p at the same size is 109. Why that gap decides text quality on macOS, plus five panels worth the money.
2026-09-02
The Best Mechanical Keyboards for Developers
Five keyboards ranked by the firmware you can actually remap — QMK, VIA, ZMK — plus the free software fix that makes buying one unnecessary.
2026-08-12
Segment Tree vs Prefix Sum Array: When O(log n) Wins
Prefix sums answer range queries in two reads but cost O(n) per update. Here is the arithmetic for when a segment tree's O(log n) update pays off.
2026-08-12
What a JIT Compiler Actually Does at Runtime
Profiling, tiering, speculation, inlining, and deoptimization in V8 and HotSpot, plus when a JIT loses to a plain interpreter.
2026-08-12
Virtual Memory and Page Faults: When RAM Runs Out
Minor faults, major faults, thrashing, and the OOM killer -- what the kernel does when a container exits 137, and the counters that tell you which one hit.
Get the best tools, weekly
One email every Friday. No spam, unsubscribe anytime.