This question separates people who think TCP "just works" from people who know it's a sender-side feedback loop. The core idea: the sender doesn't know how much capacity the path has, so it guesses — and the guess has to be cheap to recover from.
The mental model: two windows, two different problems.
Flow control is local: the receiver's advertised window (rwnd) says "I can buffer this much." Congestion control is global: the cwnd says "the network can carry this much" — and that number is invisible. Nobody on the path tells you it. So TCP must probe.
Slow start is that probe. The sender starts with a tiny cwnd — historically one segment (1460 bytes), today often 10 segments on Linux. Each ACK received doubles the window, so cwnd grows exponentially: 1, 2, 4, 8 segments per RTT. From zero, a 100MB download over a 20ms RTT needs about 14 RTTs (~280ms) to reach a multi-gigabit rate. That exponential ramp is why TCP is "slow to start" in absolute terms — the first few RTTs move almost nothing — yet it's actually the fastest safe way to find capacity.
The sender keeps growing until one of three things happens: it hits ssthresh and switches to linear growth (congestion avoidance, +1 segment per RTT), it hits the receiver's rwnd, or — the interesting case — a loss occurs. On loss, classic Reno halves cwnd and re-enters slow start below the new ssthresh. In the trace, you can see the sawtooth: exponential climb, loss, halving, climb again.
Why the deliberate waste? If you started at full speed, you'd dump tens of MB into a network that can carry tens of KB — the drop rate would explode and retransmissions would eat the gain. Starting small means the worst case is a handful of lost packets while probing, not a collapsed link. The ACK clock is the discovery mechanism: ACKs tell you both that data got through and implicitly, by their pacing, how fast the path drains.
Tradeoffs and edge cases: loss-based control is blind on high-bandwidth-delay-product paths — one drop on a 100ms RTT link can tank a video stream. That's why BBR measures pacing and RTT directly instead of waiting for loss, and why short transfers never leave slow start — a 10KB API response is done before the window has grown to even 64KB.