TCP

Transmission Control Protocol provides reliable, ordered, connection-oriented byte-stream delivery.

What TCP guarantees: - Reliability: lost segments detected via ACKs and retransmitted - Ordering: segments delivered to application in send order - No duplication: duplicate segments discarded - Connection-oriented: state established before data transfer

What TCP costs: - Connection establishment: 1 RTT for handshake - Retransmission timeout: lost packet pauses sender until retransmit - Flow control overhead: receiver advertises window size in every ACK - Head-of-line blocking: lost packet blocks all subsequent data — TCP-level HOL, not fixed by HTTP/2

Three-way handshake:

sequenceDiagram participant C as Client participant S as Server C->>S: SYN (seq=x) S->>C: SYN+ACK (seq=y, ack=x+1) C->>S: ACK (ack=y+1) Note over C,S: connection established — 1 RTT elapsed
  1. Client → Server: SYN(seq=x) — client announces initial sequence number x
  2. Server → Client: SYN+ACK(seq=y, ack=x+1) — server ACKs client's seq, announces own seq y
  3. Client → Server: ACK(seq=x+1, ack=y+1) — client ACKs server's seq

Three steps are necessary because sequence numbers must be established in both directions. Two steps would leave the server with no confirmation the client received its ISN.

ISN (Initial Sequence Number): randomly chosen to prevent TCP segment injection attacks.

Four-way teardown: FIN → ACK → FIN → ACK. Steps 2 and 3 are separate because the responder may have data left to send after receiving the initiator's FIN (half-close).

TIME_WAIT state: After the initiator sends the final ACK, it waits 2×MSL (60–120s) to: ensure the final ACK arrives, prevent old segments from a previous connection confusing a new connection on the same port. Causes port exhaustion at very high connection rates. Mitigations: SO_REUSEADDR, SO_REUSEPORT.

Flow control (sliding window): Receiver advertises receive buffer space in every ACK. Sender keeps at most window_size bytes unACKed in flight. Prevents fast sender from overwhelming slow receiver.

Congestion control: TCP infers congestion from packet loss (classic) or RTT increase (BBR). - Slow start: CWND doubles each RTT until ssthresh - Congestion avoidance: CWND grows by 1 MSS per RTT - On triple dup-ACK (loss): ssthresh = CWND/2, CWND = ssthresh (fast recovery) - On timeout: CWND = 1 MSS, restart slow start

BBR estimates bottleneck bandwidth and RTT — better for high-bandwidth, high-latency links.

Common pitfall

Opening a new TCP connection per request (instead of reusing one via keep-alive or a connection pool) pays the full 1-RTT handshake cost — plus a TLS handshake on top of it, for HTTPS — on every single request, even to the same server. This is invisible in local testing (RTT to localhost is near zero) and becomes a very real latency tax the moment real network RTT enters the picture — see Request Lifecycle for exactly where this cost lands in the full request timeline.