Heads up: posts on this site are drafted by Claude and fact-checked by Codex. Both can still get things wrong — read with care and verify anything load-bearing before relying on it.
why how

What is TCP?

IP delivers packets best-effort — they can vanish, duplicate, or arrive out of order. Almost every program wants a clean stream of bytes instead. TCP is the layer that turns one into the other.

Networking intro Apr 30, 2026

Why it exists

The internet’s foundation, IP, makes a deliberately weak promise: I’ll try to deliver this packet to that address. Not that it will arrive. Not that it will arrive once. Not that it will arrive in the order you sent it. Packets can be dropped by a congested router, duplicated by a misbehaving link, or reordered when two of them take different paths through the network.

Almost no application wants to deal with that. When you write to a socket, you want to push bytes in one end and have the same bytes — all of them, in order, exactly once — come out the other end. That gap, between what IP gives you and what programs want, is what TCP exists to fill.

TCP is old. RFC 793 (1981, Jon Postel ed.) is the original spec; RFC 9293 is the current consolidated one. The core mechanism has survived four decades of hardware change largely intact, which is itself a clue about how well the design holds up.

Why it matters now

Almost every protocol you’ve heard of runs on top of TCP. HTTP (and the HTTPS wrapping it), SSH, SMTP, IMAP, Postgres and MySQL wire protocols, Redis, every git push over SSH or HTTPS. When something is “slow to connect” or “hanging,” it’s almost always TCP behavior leaking up into the application.

It also matters because it’s what the modern alternatives are reacting against. QUIC only makes sense as a story about which specific frictions of TCP needed routing around.

The short answer

TCP = reliable, ordered byte-stream over IP = handshake + sequence numbers + ACKs + retransmits + flow control + congestion control

TCP turns IP’s best-effort packet delivery into a byte stream between two endpoints. It opens the connection with a handshake, numbers every byte it sends, has the receiver acknowledge what it got, retransmits what wasn’t acknowledged, reassembles out-of-order arrivals, and adapts its sending rate to both the receiver’s capacity and the network’s.

How it works

Five mechanisms, each doing one job.

Connection setup — the 3-way handshake. Before any data flows, both sides exchange three messages. The client sends SYN with its initial sequence number. The server replies SYN-ACK: it acknowledges the client’s number and announces its own. The client replies ACK. Why three and not one? Each side needs to tell the other its starting sequence number and confirm the other received that number. The third message is what makes confirmation symmetric.

Reliability — sequence numbers and ACKs. Every byte TCP sends has a number. The receiver sends back ACKs that say “I have everything up through byte N.” If the sender doesn’t see an ACK within a timeout (and modern TCP estimates the path’s RTT and adapts), it retransmits. Duplicates the receiver simply discards. The apparatus turns “packets sometimes vanish” into “the application sees every byte exactly once.”

Ordering. Packets routinely arrive out of order. The receiver buffers them, looks at sequence numbers, and only hands bytes up to the application in order. If byte 1000 arrives before byte 900, it sits in the buffer until 900 arrives.

Flow control. A fast sender talking to a slow receiver could drown it. So every ACK carries a window — “I have room for this many more bytes.” The sender can’t have more than that many bytes unacknowledged in flight. It’s the receiver’s volume knob on the sender.

Congestion control. Distinct from flow control: flow control protects the receiver, congestion control protects the network in between. The sender keeps its own window that grows on clean ACKs and shrinks on loss, reading loss as a hint that some router on the path is full. This gets its own post — see TCP congestion control for AIMD, CUBIC, BBR, and why it exists at all.

Connection teardown. Either side can send FIN (“no more data”); the other ACKs, then sends its own FIN, ACKed back. Closes are independent per direction — half-closed connections are legal.

Show the seams

This is where TCP’s age shows.

Going deeper