When a page loads slowly, an API times out, or packet capture shows retransmissions and duplicate acknowledgements, the problem is often not HTTP itself. It is the transport connection beneath it. TCP is usually summarized as a “reliable transport protocol,” but the real engineering judgment comes from how it turns an unreliable network path into a usable byte stream through connection state, acknowledgement, retransmission, windows, and in-order delivery.
TCP’s cost is here too. It solved the reliable transport problem for the open Internet, but it also carried later Web performance constraints, weak-network behavior, and multiplexing limits down below the application layer. The reasons HTTP/2 gets stuck behind packet loss and QUIC wants to redesign transport again are both in TCP’s behavior model.
TCP does not mainly “guarantee data arrival.” It uses connection state, acknowledgements, retransmission, window control, and in-order delivery to build a sustainable byte stream on top of unreliable IP
Why It Appeared
IP solves “try your best to deliver packets to the destination address.” It does not solve “deliver a complete data sequence reliably for an application.” In the earlier network reality, that led to several problems:
- Packets could be lost
- Packets could arrive out of order
- Packets could arrive more than once
- The sender could be much faster than the receiver
- The entire network could get congested under excessive sending
If every application had to solve those problems by itself, the cost would be high and interoperability would be poor. TCP’s value was to collect those common problems into one generic mechanism so applications could receive a continuous byte stream instead of a pile of disordered packets.
Who Built It and Under What Conditions
TCP came out of the early Internet protocol stack, driven by DARPA-supported work, and later became a key part of the TCP/IP family. It was not designed for a single vendor’s controlled data center. It was designed for heterogeneous hosts, long-distance links, and an unstable public Internet.
That set the design priorities:
- The underlying network is assumed to be unreliable
- The two endpoints are assumed to differ in speed and capability
- A connection may last for a while rather than ending after one packet
- Once deployed at scale, compatibility has to last a long time
So TCP is not a protocol optimized only for “fast file transfer inside a LAN.” It is a deliberately conservative, general-purpose transport layer for the open Internet.
Main Model
TCP is easiest to think of as four keywords:
- Connection-oriented
- Byte-stream oriented
- Acknowledgement and retransmission
- Flow control and congestion control
The byte-stream part is easy to underestimate. TCP does not know where one HTTP request, TLS record, or custom protocol message starts and ends. To TCP, the application hands over a sequence of bytes, and TCP tries to deliver that sequence to the other side reliably and in order.
That is both its strength and the source of many limits.
A Typical Path
Behind that simple path, TCP is doing several things at once:
- Confirming that both sides are willing to create a connection
- Establishing sequence number space in both directions
- Telling the other side which bytes have been received
- Triggering retransmission when data is lost
- Using windows and congestion control to avoid overwhelming either endpoint or the network
What looks like three-way handshake plus a stream of ACKs is really a continuously maintained connection-state machine.
Why Three-Way Handshake Exists
The point of the three-way handshake is to let both sides confirm two things:
- The peer is reachable
- The initial sequence numbers and connection state have been established
It can be shown like this:
With only two steps, the server would not know whether the client received its SYN+ACK, and the connection state could remain half-open. The third step closes the loop and makes both sides know that the other side can send and receive.
That is why, when you see many SYN packets but not a complete three-way handshake, you usually start by checking reachability, firewalls, listening ports, or packet loss in the middle, not the application protocol first.
Why TCP Delivers In Order
TCP is not only reliable; it also promises in-order delivery. That simplifies application code:
- Applications do not need to reorder out-of-order data themselves
- Upper-layer protocols can parse a continuous byte stream
- Many older protocol implementations can stay simple
The cost is large. If one earlier segment is missing, later data that has already arrived cannot be passed up yet. That is the root of TCP head-of-line blocking.
This design was natural for file transfer, database connections, and early Web traffic, where one connection usually carried one linear stream. Once HTTP/2 started multiplexing many requests over one connection, the problem became much more visible.
Why Acknowledgements and Retransmission Cost Performance
TCP trades reliability for acknowledgement and retransmission, but those are not free.
When a segment is lost, the sender usually detects it in one of two ways:
- A timeout expires before acknowledgement arrives
- Repeated duplicate acknowledgements suggest a missing segment in the middle
The missing data is then retransmitted. That keeps reliability intact, but it also creates follow-on costs:
- Waiting for acknowledgements increases latency
- Retransmission consumes bandwidth
- In-order delivery delays data that already arrived later
- Congestion control may reduce sending speed further
So the other side of “TCP is reliable” is that it spends more waiting, more state, and more conservative control to earn that reliability.
Why Window Control Is Necessary
TCP cannot let the sender run at full speed forever. There are at least two different limits.
The first is the receiver. It may not be able to absorb data fast enough, so the receive window tells the sender how much more it can take.
The second is the network itself. It may not tolerate a sustained high send rate, so congestion control limits how much data enters the path.
These two windows are often confused, but they solve different problems:
- The receive window answers “can the other side keep up”
- The congestion window answers “can the network keep up”
If throughput looks bad and you do not separate those two, it is easy to mistake a window issue for “not enough bandwidth.”
Why HTTP/2 Still Gets Stuck on TCP
HTTP/2 already multiplexes in the application layer, so multiple requests and responses can share one connection. But the transport beneath it is still TCP.
That means:
- Multiple HTTP/2 streams share one TCP byte stream
- If one TCP segment is lost, later segments, even for other streams, still have to wait
- Application-layer multiplexing does not remove the transport-layer in-order blocking
That is why QUIC moved multiplexing semantics down into the transport layer. HTTP/2 has streams, but TCP only sees one byte stream.
What Four-Way Close Is Solving
Connection close is not just “disconnect.” TCP is full duplex, and both sides may still have data to send, so shutdown happens in two steps:
One side sends FIN to say “I am done sending.” The other side acknowledges that, but it can still send its own remaining data before closing with its own FIN. That is why four packets are needed.
So when a connection enters FIN_WAIT or TIME_WAIT, it is still inside the close sequence, not fully released yet.
What to Look At in a Capture
TCP analysis is easiest if you do not start from the full header. A better order is:
First, Confirm the Connection Was Established
Check whether:
SYNSYN+ACK- Final
ACK
all completed. If the three-way handshake did not finish, check reachability, firewalls, listening ports, or middlebox loss before looking at the application.
Then Look for Retransmission, Duplicate ACKs, and Reordering
These signals carry a lot of meaning:
RetransmissionDup ACKOut-of-OrderZero Window
They usually point to loss, receiver pressure, link instability, or path-quality issues.
Finally Check RTT and Window Changes
Many “sometimes fast, sometimes slow” problems are not caused by server logic alone. They are often caused by:
- RTT growth
- Congestion window shrinkage
- Receive window shrinking
- Retransmission disturbing the sending rhythm
If you only watch application latency and ignore this layer, the conclusion is often wrong.
How to Read TCP in Engineering Work
- TCP is not just “reliable transport.” Its main cost is connection state, in-order delivery, and retransmission control
- A byte stream is not a message stream, so the application must define message boundaries itself
- Head-of-line blocking comes from TCP’s in-order delivery, not from HTTP/2 inventing extra trouble
- Throughput problems are not only about bandwidth; windows, RTT, loss, and congestion control are often more important
- QUIC is not a renamed TCP. It moves the transport-layer choices that modern Web needs into a new design
Further Reading
- How TCP States Show Where a Connection Is Stuck: how SYN, ESTABLISHED, CLOSE-WAIT, and TIME-WAIT help locate connection phases
- Why TCP Congestion Control Makes Networks Slower After Loss: how congestion windows, RTT, loss, and RTO affect throughput
- IP: the network layer that provides reachability, routing, and best-effort forwarding
- NAT: why TCP connections still depend on state maintenance across address rewriting
- HTTP: why application semantics and intermediaries are built on top of TCP
- HTTPS: how
TCP + TLSputs HTTP into a secure channel - QUIC: why modern Web traffic works around some of TCP’s cost