TCP and UDP
TCP and UDP are not simply “reliable versus unreliable.” TCP provides a reliable ordered byte stream with flow and congestion control, connection state, retransmission, and head-of-line behavior. UDP provides independent datagrams with minimal transport semantics; applications or higher-level protocols such as QUIC add the reliability, ordering, security, and congestion behavior they need. Senior candidates reason about failure detection, retransmission ownership, connection lifecycle, and overload—not only header differences.
How to use this chapter
- Read the mental model and mechanics without taking notes.
- Close the page and explain the topic aloud in five minutes.
- Work the quantitative example on paper.
- Answer the question ladder without revealing the answer signals.
- Complete one design drill and score yourself with the senior checklist.
Learning objectives
- Explain TCP setup, byte-stream semantics, sequence numbers, acknowledgments, retransmission, and teardown.
- Distinguish flow control from congestion control and connect both to throughput and latency.
- Explain UDP datagrams, loss, duplication, reordering, size/MTU constraints, and application responsibility.
- Compare TCP, UDP, and QUIC for common system-design workloads.
- Design connection pools, timeouts, keepalives, heartbeats, retry behavior, and graceful drain.
- Diagnose retransmission, head-of-line blocking, SYN pressure, and reconnect storms at senior level.
Mental model
UDP sends messages without establishing transport state or guaranteeing delivery/order. That makes it suitable when the application prefers freshness over recovery, needs multicast-like patterns, or implements a richer transport. QUIC uses UDP as a substrate while providing secure connections and independent streams, reducing some TCP-level head-of-line effects.
Core mechanics
TCP connection lifecycle
TCP commonly begins with a three-way handshake that synchronizes sequence state. TLS and application negotiation may add more round trips unless resumed or combined by another transport. Connection reuse amortizes setup and allows congestion state to warm, but creates pool sizing, idle timeout, stale connection, and load-balancing concerns.
Teardown can be graceful with FIN in each direction or abrupt with reset. Half-closed connections are possible. Intermediate NATs and proxies may drop idle state earlier than endpoints expect, so application protocols often use keepalives or heartbeats—but excessively frequent heartbeats waste battery and fleet bandwidth.
Reliable ordered byte stream
TCP numbers bytes, acknowledges received ranges, detects loss, and retransmits. Applications see a stream, not messages: one send does not correspond to one recv. Protocols must define framing using lengths, delimiters, or self-describing formats and must handle partial reads/writes.
Ordered delivery means a missing segment blocks delivery of subsequent bytes to the application even if they arrived. Multiplexing many logical requests over one TCP connection can therefore couple their latency at the transport layer, in addition to any application-level queueing.
Flow control and backpressure
Flow control protects the receiver. The receive window communicates how much buffer space is available; a slow application can shrink the window and eventually stall the sender. This is not an error—it is backpressure—but unbounded application buffers above TCP can defeat it and turn slowness into memory exhaustion.
At the application level, bounded queues and streaming APIs should propagate slow-consumer signals. A successful socket write may only mean data entered a local buffer, not that the peer read or processed it.
Congestion control and loss recovery
Congestion control protects the network by adapting the sending rate based on acknowledgments, loss, and timing. New or idle connections may start below path capacity and ramp up. Packet loss reduces the congestion window and can sharply hurt throughput on long-RTT paths.
Retransmission can be triggered by duplicate/selective acknowledgments or timers. Timer-based recovery is comparatively slow, so tail latency can jump after a single loss. Modern algorithms vary, but interview reasoning should stay at the level of in-flight data, RTT, loss, and fair sharing unless a specific implementation is requested.
UDP semantics
UDP preserves datagram boundaries and adds ports plus a checksum, but it does not ensure delivery, order, uniqueness, congestion control, or connection establishment. Datagram size must respect path constraints; IP fragmentation is fragile, so applications usually keep packets below a safe size or implement chunking.
UDP applications need sequence numbers, timeouts, deduplication, loss handling, rate/congestion control, and security if those properties matter. “Fire and forget” is acceptable only when loss and abuse consequences are understood.
QUIC and transport choice
QUIC runs over UDP, integrates TLS, and provides reliable streams. Loss in one stream need not block delivery on other streams at the transport layer. Connection identifiers can help connections survive address changes, useful for mobile clients. User-space implementation enables faster evolution but moves more work outside the kernel and can face UDP-blocking or middlebox constraints.
HTTP/3 maps HTTP semantics over QUIC. It is not universally faster; benefits depend on RTT, loss, connection reuse, CPU, and network support. A senior answer proposes measurement and fallback rather than declaring a winner.
Timeouts, keepalive, and failure detection
TCP can remain apparently established while a peer or path is gone, especially without traffic. Kernel keepalive defaults may be far too slow for application failover. Application heartbeats can detect failure faster and carry semantic state, but detection time trades against false positives and cost.
Separate connect timeout, TLS timeout, request deadline, read/write idle timeout, and connection max age. During deployments, gracefully stop accepting new work, drain in-flight requests, notify long-lived clients, and add reconnect jitter.
Decision table
| Decision | Prefer the first option when… | Prefer the second option when… | Senior caveat |
|---|---|---|---|
| TCP vs UDP | Reliable ordered streams and broad middlebox compatibility are desired. | Freshness, datagram semantics, custom transport, or QUIC-like behavior is required. | UDP does not excuse congestion control or security; TCP does not provide application exactly-once. |
| One multiplexed connection vs connection pool | Handshake amortization and low connection count dominate. | Per-connection bottlenecks, stream limits, or failure isolation favor multiple connections. | Too many connections increase memory, ports, handshakes, and unfairness. |
| Transport keepalive vs application heartbeat | Only dead-path detection is needed and coarse timing is acceptable. | Fast semantic liveness and per-session health are needed. | Coordinate with proxies/NAT idle timeouts and battery/network cost. |
| Retry same connection vs new connection | Failure is request-level and connection remains trustworthy. | Connection is reset, wedged, or path/backend selection should change. | Respect idempotency and retry budget; new connections add handshake and load. |
| Large stream vs chunked independent units | Order and simple streaming dominate. | Parallel recovery, resumability, and bounded retries matter. | Chunk IDs, checksums, and assembly state become application responsibilities. |
| TCP/TLS vs QUIC | Mature infrastructure and predictable proxy support dominate. | High-RTT/loss, multiplexing, mobility, or handshake reduction shows measured benefit. | Maintain fallback and compare CPU, not only latency. |
Quantitative reasoning
Failure modes and production signals
| Failure mode | What users see | Likely cause | Mitigation / design response | Useful signals |
|---|---|---|---|---|
| Retransmission spike | Higher p99 and lower throughput | Congestion, bad link, overloaded NIC/host | Locate loss segment, reduce overload, add path/capacity, tune only after diagnosis | Retransmits, RTT, congestion window, drops by interface |
| SYN/accept pressure | New connections fail; established traffic may work | Connection storm, attack, small backlog, CPU | DDoS controls, SYN defenses, reuse, scale listeners, backpressure | SYN rate, accept queue, handshake latency, resets |
| Slow receiver | Sender memory grows or writes stall | Client cannot consume, receiver window closes | Bound buffers, per-client quotas, drop/coalesce stale data, disconnect | Send queue, zero-window events, connection memory |
| Idle state expiry | First request after idle resets | NAT/proxy timeout shorter than endpoint expectation | Keepalive/heartbeat below timeout, connection validation, retry safely | Connection age, resets after idle, intermediary timeout logs |
| Reconnect storm | CPU/handshake saturation after outage | Clients retry simultaneously | Exponential backoff, jitter, admission, session resumption, staged recovery | New connections/s, TLS CPU, retry interval distribution |
| UDP amplification/abuse | Unexpected egress and service overload | Spoofable requests with larger responses | Authenticate/cookie before large response, rate limit, response size discipline | Request/response byte ratio, source distribution, drops |
Senior-level lenses
Transport acknowledgment is not business acknowledgment
TCP confirms bytes reached the peer transport stack, not that an order was committed or a message was durably stored. Application protocols need request IDs, commit acknowledgments, idempotency, and reconciliation. This distinction is central in payment, queue, and replication designs.
Connection pools are capacity controls
Pool size sets concurrency against a dependency. An unbounded pool can overload the server; a tiny pool creates queueing. Size using service time, target utilization, per-connection multiplexing, and downstream limits, then expose queue wait separately from request latency.
Head-of-line exists at several layers
TCP ordered delivery can block later bytes after loss. HTTP/1.1 pipelining and application queues can add their own ordering. HTTP/2 multiplexes streams but still shares TCP loss recovery. QUIC reduces cross-stream transport blocking but does not eliminate server, connection, or application bottlenecks.
Failure detection is a trade-off
Short heartbeats detect failure quickly but consume resources and increase false positives during transient pauses. Long timeouts slow failover. Use leases and phi-like or adaptive approaches where needed, and distinguish suspected failure from authoritative fencing.
Mobility and identity are separate
An IP/port change does not necessarily mean the logical user or QUIC connection changed. Conversely, a stable TCP connection is not proof of authorization. Bind sessions to cryptographic identity and rotate credentials independently of transport lifetime.
Test the degraded network
Benchmarks on a clean low-RTT network hide retransmission, reordering, bandwidth asymmetry, and mobile handoff. Inject latency, jitter, loss, duplication, resets, and NAT expiry; observe retries and user semantics, not only raw throughput.
Interview question ladder
What guarantees does TCP provide?
Show strong-answer signals
Reliable, ordered byte stream with duplicate suppression, flow and congestion control between endpoints; no message boundaries or application commit/exactly-once guarantee.
What guarantees does UDP provide?
Show strong-answer signals
Best-effort datagrams with ports and checksum; messages may be lost, duplicated, reordered, or fragmented, and no built-in congestion control/handshake.
What is the difference between flow control and congestion control?
Show strong-answer signals
Flow control protects the receiver’s buffers; congestion control adapts to path/network capacity.
Why must a TCP application implement framing?
Show strong-answer signals
TCP is a stream; sends can be split/coalesced. Use length prefix, delimiter with escaping, fixed frames, or self-describing encoding and handle partial I/O.
Why can packet loss hurt TCP throughput more on a high-RTT path?
Show strong-answer signals
Recovery feedback/timers take longer and congestion window reduction limits in-flight data; relate to BDP and retransmission.
When would you choose UDP for an application protocol?
Show strong-answer signals
Freshness over completeness, low-latency media/game state, discovery, or as substrate for QUIC/custom reliability—while adding congestion, security, sequencing as required.
A chat gateway’s memory grows when some mobile clients have poor connectivity. What is happening?
Show strong-answer signals
Slow receivers cause send queues; TCP backpressure may not reach app because buffers are unbounded. Bound per-connection queues, coalesce presence/typing, persist messages elsewhere, and disconnect/replay.
How would you design connection pooling for a service calling a database proxy?
Show strong-answer signals
Account for max server connections, per-connection multiplexing, query concurrency/service time, queue bound, timeouts, lifetime, health validation, failover, and tenant fairness.
Compare HTTP/2 over TCP and HTTP/3 over QUIC during packet loss.
Show strong-answer signals
HTTP/2 streams multiplex but TCP loss can block delivery across streams; QUIC has stream-level reliability so one stream’s loss need not block others. Include handshake, CPU, fallback, and application/server bottlenecks.
Design reconnect behavior for ten million clients after a regional outage.
Show strong-answer signals
Exponential backoff with full jitter, server retry hints, admission tokens, regional routing, session resumption, progressive capacity restoration, per-client caps, and observability of attempt cohorts.
Design a low-latency market-data transport where newer updates supersede older ones.
Show strong-answer signals
UDP/multicast or QUIC datagrams where supported, sequence numbers, snapshots plus deltas, gap detection/recovery channel, congestion/rate policy, authentication, clocks, and regional loss behavior.
A global service sees rare duplicate payments despite TCP. Explain all duplicate paths and defenses.
Show strong-answer signals
Client timeout before response, proxy retry, server crash after commit, connection reset, consumer redelivery. Use idempotency key, atomic dedupe/commit, durable response lookup, retry policy, and reconciliation.
Design drills
Design transport for a 60-player game: position updates at 20 Hz, reliable inventory changes, chat, and match results. Choose protocol/stream semantics for each and describe loss, ordering, congestion, and cheating controls.
What the interviewer is testing
Per-message semantics rather than one-protocol dogma; freshness, reliability, and security.
A 5,000-instance fleet restarts and each instance opens 50 database connections. The database accepts only 20,000. Design startup, pooling, proxying, and admission behavior.
What the interviewer is testing
Connection state as scarce capacity, jitter, hierarchical pools, backpressure, and safe recovery.
Design a 20 GiB upload protocol over unreliable mobile networks. Include chunking, checksums, resumability, parallelism, idempotency, and final commit semantics.
What the interviewer is testing
Transport versus application reliability, bounded retry, integrity, and durable acknowledgment.
Common weak answers and how to improve them
“TCP means the operation happens once.”
Show the stronger answer
TCP handles byte delivery; application retries and crash timing still create duplicate operations.
“UDP is faster.”
Show the stronger answer
State which omitted semantics reduce latency and which must be rebuilt; include congestion, security, and loss behavior.
“Use keepalive.”
Show the stronger answer
Specify transport versus application heartbeat, interval, intermediary timeout, false positives, and fleet cost.
“Open more connections for throughput.”
Show the stronger answer
Calculate BDP/window and account for ports, memory, server limits, fairness, and handshake load.
“Connection established means the peer is healthy.”
Show the stronger answer
It may be half-open or the application may be wedged; use deadlines and semantic health signals.