TCP gives you a reliable ordered byte stream; UDP gives you raw packets with no guarantees. The choice isn't about 'which is better' — it's about what your application can tolerate. Get this wrong and you either pay for reliability you don't need or build reliability that already exists.
What TCP gives you
Reliable delivery (retransmit lost segments). In-order delivery (buffer out-of-order arrivals). Flow control (slow sender if receiver is slow). Congestion control (slow down on packet loss). All of this comes with handshake latency (1 RTT) and head-of-line blocking.
What UDP gives you
Send packet → it arrives or it doesn't. No retransmit, no ordering, no flow control, no handshake. You're responsible for everything TCP gives you for free — but you also get to skip everything you don't need.
Pick UDP when
Audio/video real-time: late retransmits are useless (decoder already moved on). Game state updates: only the latest position matters; old positions are stale. DNS queries: one packet, one response, lower latency. Custom protocols (QUIC) that need stream-level retransmission.
Pick TCP when
File transfer: every byte must arrive in order. HTTP: most servers expect TCP. Database connections: stateful, sequenced. Anything where loss = data corruption.
Build-your-own reliability on UDP
Common patterns: sequence numbers + selective ACK (custom protocol). FEC for forward error correction without retransmit. Send-twice for critical packets. Application-level retransmit only for state-relevant events, not for stale data. QUIC is the canonical implementation.