Why TCP Exists
Making Unreliable Networks Actually Useful

I'm a passionate backend dev
In the last article, we saw something important.
Data moving across a network is… messy. Bits get lost. If you send 10 packets via IP, they might arrive out of order. Some might get lost because a router some where got overwhelmed. Some might even arrive twice. IP doesn’t care. It’s "best effort." It’s like a postal service that says, "I’ll try to deliver your letter, but if I drop it in a puddle, I’m not coming back to tell you."
If we built apps directly on top of that, Netflix would glitch every three seconds, and your bank transfers would be a gamble.
At first, this feels broken. But here’s the real question:
If the network is this unreliable, how did we ever build anything useful on top of it?
That question is exactly where TCP comes from.
Let’s Start With a Frustrating Situation
Imagine you want to send a digital book to a friend, but the post office only allows you to send one page at a time in separate envelopes.
If you just start mailing pages, a few things will go wrong:
The friend receives page 10 before page 2.
Page 45 gets eaten by a sorting machine and never arrives.
You send pages so fast that your friend’s mailbox overflows and the mailman starts throwing them in the trash.
If this was the end of the story, the internet would be unusable
What We Actually Want
Before talking about TCP, let’s talk about expectations. When you send data, you assume a few things:
The other side receives everything
The data arrives in the right order
Nothing is duplicated
If something fails, it’s retried
Notice something? None of this is guaranteed by the network itself. So someone had to step in and say: “Fine. I’ll handle this mess.”
That “someone” is TCP.
TCP Doesn’t Make the Network Reliable
This is a subtle but important point. TCP does not fix the network.
Packets still get lost. Delays still happen. Chaos still exists underneath.
What TCP does is manage the chaos. It accepts the network’s unreliability and builds rules on top of it.
The First Big Idea: A Conversation, Not Shouting
Before TCP, sending data was like shouting into the dark. TCP changes that. It says: “Let’s first agree that we’re talking.”
This is where the idea of a connection comes from. Not a physical wire. Just an agreement between two machines (The Handshake):
“I’m here” (SYN)
“You’re here” (SYN-ACK)
“Let’s talk”(SYN)
This alone removes a huge amount of uncertainty.
Knowing What Was Received
Here’s another simple but powerful idea. What if the receiver could say: “I got this part.” And if something wasn’t received: “I didn’t get that part.”
That’s acknowledgements. TCP numbers pieces of data and expects confirmations back. If something doesn’t get acknowledged, TCP assumes: “It probably got lost. I’ll send it again.”
No panic. No guessing. Just calm retries.
Keeping Things in Order
Remember how pieces could arrive out of order?
TCP handles that too. Each piece has a number. The receiver reassembles them in the correct order. Even if piece 10 arrives before piece 4, TCP patiently waits and rearranges. To the application, everything looks clean and ordered.
Avoiding Overwhelm
There’s another problem we haven’t talked about yet.
What if the sender is too fast?
Sending data faster than the receiver can process it causes: Memory pressure, Drops, Failures.
TCP solves this with a surprisingly human idea: “Don’t talk faster than the other person can listen.” This is flow control. The receiver tells the sender how much data it can handle. The sender adjusts.
A conversation, not a monologue.
Reacting to a Busy Network
Sometimes the problem isn’t the receiver. The network itself gets crowded. Routers get overwhelmed. Queues fill up. Packets get dropped.
TCP watches for signs of this and slows down.
Not because it’s polite. Because pushing harder would break everything.
This is congestion control.
What TCP Finally Gives Us
After all this work, TCP gives applications something precious:
Reliable delivery
Ordered data
No duplicates
A continuous stream of bytes
From the application’s point of view, the mess is gone. It feels like reading from a pipe where data just… arrives. This illusion is incredibly powerful.
Why TCP Was a Big Deal
Without TCP:
Every application would have to solve reliability
Every developer would reinvent the same logic
Most systems would be buggy and fragile
TCP centralizes this complexity. It says: “You focus on your application. I’ll handle delivery.”
This single decision shaped the modern internet.
Why Backend Engineers Should Care
If you don’t understand TCP:
Timeouts feel mysterious
Retries feel arbitrary
Latency feels random
If you do understand TCP:
Failures feel explainable
Performance tuning makes sense
System behavior becomes predictable
You stop blaming “the network” and start reasoning about it.
A Quiet Tradeoff (Important)
TCP gives us reliability. But it’s not free. It adds:
Overhead
Latency
Coordination
And sometimes… we don’t want that. That realization leads to an interesting question.
What Comes Next
If TCP is reliable but heavy, then: “When would we not want TCP?” That’s where UDP enters the story.
➡️ Next article:
UDP: Fast, Honest, and Unreliable (By Design)
This article is part of the Thinking in Backend series, where we learn backend engineering by focusing on how systems think, not just how code runs.




