I understand that TCP flow control provides a way for the receiver to backpressure the sender. But what if we eliminated this from the protocol. Of course, the receiver would still ACK everything that is received and successfully saved in a buffer or transferred to application layer, but would simply drop everything else. The sender would re-transmit and this would ensure reliable delivery.

Why doesn't this work? I could see that this would cause a part of network capacity to be wasted on dropped packets. But it saves on the complexity of implementing sliding window.


  • 2
    I could see that this would cause a part of network capacity to be wasted on dropped packets. But it saves on the complexity of implementing sliding window.. Why do you assume the design complexity, which only has to be done once, is more expensive than wasting network capacity? – Ron Trunk Jan 28 at 3:57
  • 1
    There's no way you could actually turn off flow control as an integral component of TCP, short of defining an infinite send window. – Zac67 Jan 28 at 10:03
  • "My question is about what would happen, behaviorally, if TCP flow control is turned off?" Based on your comment, you are asking the impossible because it is built into the very foundation of TCP. Basically, you are asking for guesses and opinions, which are off-topic, because there is no way to test this. You would need to rewrite TCP and leave out flow control to test such a thing. Also, it would not be TCP, so you are asking a question about a non-existent protocol, and that is off-topic here. – Ron Maupin Jan 28 at 21:47

But what if we eliminated this from the protocol.

Then it would not be TCP.

The point of flow control is that the receiving host has a buffer to receive data, and it is a fixed size. The receiver tells the sender what the available buffer space is left in the acknowledgements. As the receiving TCP receives data and fills the buffer, the window shrinks, and as the TCP gives data to the application and frees buffer space, then the window grows. If the receiver can keep up with giving data to the application, then the window can keep up with the sender.

Flow control is what TCP is built around. The flow control is based on the window sent back in every acknowledgement. If you do not want flow control, then you use a different protocol. Usually, you would use UDP and create an application-layer protocol that implements the other TCP features that you want. This is often done by programmers.


RFC 793, Transmission Control Protocol explains that flow control is a required part of reliable communication (I have highlighted the relevant text):

To provide this service on top of a less reliable internet communication system requires facilities in the following areas:

Basic Data Transfer
Flow Control
Precedence and Security

Remember that IP (both IPv4 and IPv6) is an unreliable protocol on top of which TCP rides

  • 1
    "This is often done by programmers." You just made my day! :-) – Marc 'netztier' Luethi Jan 28 at 12:46
  • 2
    The result is usually much less efficient than TCP because data gets dropped a lot due to full buffers. TCP has been refined and proven over the years. Many people dislike it, but they really do not understand it. – Ron Maupin Jan 28 at 12:49
  • 1
    For realtime communication systems that can tolerate some amount of loss (eg. TV) UDP works just fine. But, yes, some mechanisms are needed to determine what the path can sustain. TCP is too rigid for such systems. On the other hand, when you transfer a file, it's important that every bit make it across unchanged -- speed is sacrificed to attain that accuracy. (TFTP is, of course, the exception to prove the rule -- it's needlessly slow and stupid.) – Ricky Jan 28 at 13:07
  • Thanks for the answer. I understand how TCP flow control works. Also the concern here is not over the definition of TCP. My question is about what would happen, behaviorally, if TCP flow control is turned off? A second question is why was flow control designed into TCP initially? – Shuheng Zheng Jan 28 at 18:24
  • "This is often done by programmers." - well, it was done at least in web browsers with introduction of QUIC protocol (see my updated answer below). The second question is also answered in my update. – Tomasz Pala Jan 29 at 9:26
  • Assume a sender / server connected to its local network at 10Gbps.
  • Assume 10Gbit/s networking from the sender to the WAN Edge router of it's datacenter.
  • Assume a WAN Edge Router with 10Gbps on the datacenter side and multiple WAN circuits of 100Mbps each.
  • Assume a WAN Router at one of the spoke sites, with 100Mbps WAN and 1Gbps LAN connectivity.
  • Assume the receiver being connected to that spoke site LAN with 1Gbit/s.

Being initiator and receiver, a client system at a spoke site requests to download a file from a server at the datacenter.

The server, being responder and sender, will quickly start to blast away at 10Gbps. The WAN Edge router will instantly fill up its egress queue/buffer to the WAN circuit, and tail-dropping will start.

If the sender won't throttle it's sending rate, the WAN router will continue to be tail dropping at an insane rate, effectivley DoS'ing the WAN circuit, for ALL users at the other end of the given 100Mbps circuit.

What's more - if the network path from sender to receiver is likely to be dropping >90% of all packets, the sender will have to keep a LOT more of the data to be sent (and possibly re-sent) in a buffer, further increasing the system ressources demands on the server/sender side (... large scale buffering for potentially 100s of client/receivers).

That's why there is flow control/congestion avoidance in TCP, so the sender has a metric to estimate the allowable sending rate individually per receiver, and it can throttle down to a level where the rate of missing ACKs and retransmissions becomes marginal or zero.

This also ensures some degree of fairness for other data flows competing for bandwidth across a narrow link.

  • 1
    Congestion detection is yet another mechanism to keep all this sane. Flow control is established by controlling the send window, which would need to be infinite (which an infinite amount of buffering) - with the effects you're describing. – Zac67 Jan 28 at 10:04
  • Thanks for the answer! Is DDoSing possible though? I would think there is a kind of fairness mechanism at work on the Router to prevent one flow from taking over the bandwidth? – Shuheng Zheng Jan 28 at 18:27
  • Such fairness mechanisms exist, they're called QoS, but they are NEVER automatically doing the "right thing"; getting QoS right fills books, and is only really feasible end-to-end within a single administrative domain - and never across the open Internet. Even with a perfect QoS implementation, a router would still do the same thing as without: Drop packets at an insane rate, while being forced to fail at stuffing a 10Gbit/s stream into a 100Mbit/s circuit. – Marc 'netztier' Luethi Jan 28 at 20:55
  • Actually, when you degrade the L2 connection, like transition from 10G port to 1G one in a switch, entirely different and new set of problems arise. This is called "micro bursts", is related to low buffer space on the switch and is being managed by CoS (ToS, DSCP) not QoS. And this has nothing to do with "fairness" - this problem emerges from the media speed itself and occurs even with two end-points (sender-10G_switch_1G-receiver). CoS can manage multiple streams competing within one L2 device, while QoS runs on L3. – Tomasz Pala Jan 29 at 9:34

Actually this is not only a theoretical question. There were (are?) problems with BBR alghorithm which was too aggressive and was taking over streams with "classic" congestion mitigation mechanisms (like Cubic), apparently something like described here. AFAIR this was the reason for BBRv2 adjustments.

In such situation (abusive pacing) one stream takes over the entire bandwidth with some unfair ratio (depending on "aggaressiveness"), so other services run degraded, except for the abusive stream itself.

So if you ask for no flow+congestion avoidance at all: this will break every transmission (including own) on every link that gets overflown - after (during) jamming other streams it will inevitably make itself overflow too.

As noted by Ron Maupin in the comment below, this answer is about congestion, not flow control; however, since flow control handles entire end-to-end communication, while congestion considers the network capacity, it's obvious that flow control is irrelevant if the network (well, just include endpoints as parts of it) is not capable of delivering packets.

Thus the answer would be more complicated:

  1. if you only want to disable (make it ineffective in practice, anyhow) flow control, you could observe higher network utilization and packet drops, but no other effects - since the congestion avoidance might (like BBR) use the dropped packet metric to slow down sending, or much different issues depending on congestion control used by the sender; in particular, if sender doesn't use drop-resilient CC the stream would be unstable or even stall,
  2. if you meant disabling every stream speed control knobs (i.e. both, flow and congestion control) - the effects would be like described above, similar to UDP flood.

In short: disabled flow control (window big enough to be practically infinite) will cause excessive traffic and packet drops [but the transmission itself could be (depending on congestion control metrics used) intact; after all, every drop should be retransmitted, or expose direct effects of packet drops itself.]

As for the 2nd comment - yes, that distinction is crucial. Flow control being proactive (and declarative: "how much can(not) I take"), while congestion control retroactive (and using "hidden variables" like drop rate or RTT). In order to completely break the TCP one has to inactivate both of them, i.e. make the abusive change at least on sending side (aggressive/non congestion and ignoring flow control parameters by setting and keeping huge window); receiving party cannot exploit flow control to request unfair share of the bandwidth.

In a very simplified form one could say that while congestion control is about fairness, the flow control is about dropless. And to be honest ...both of them were failing on their job. Flow control cannot prevent random drops generated in dynamic environments (like wireless), while all the classic and even the modern CC algorithms didn't cope well in general sense "fairness". One might even say that TCP is obsoleted and such statement is also truish. These (and many others) shortcomings were addressed in QUIC protocol which were implemented in web browsers to overcome long release cycles of dominating operating systems. Fixing the TCP to catch up with modern world involved BBR - it is drop resilient and has fast convergence (dynamic, adaptiveness). And since v2 is not overwhelming against other streams and has it's own TCP pacing, so doesn't require FqCoDeL qdisc on L2 interface. This is how different elements of calculating stream desired speed are intertwining now.

As for the "extra complexity" of sliding window - in any asynchronous variable-length packet transmission protocol you need some kind of buffer management anyway. Building it in a way that can expose the available window space is some extra effort, but it's not like you could ditch this thing entirely.

Also, remember that TCP was designed decades ago and what you consider "some little overhead" currently was a really huge and unacceptable loss in times, where available bandwidths were orders of magnitude slower than today. Back then, without advanced congestion control, drop ratios beyond some threshold would lead to sudden stall of the stream, so not only the tiny bandwidth would be wasted on retransmissions, but also it couldn't be effectively used. Just think about 9600 baud fixed line with about 70% maximum utilization, when 3% drop rate nukes the transmission; if such line were noisy, the TCP would simply not work over it.

  • 1
    Flow control and congestion control are two very different things. The question is about flow control, not congestion control. – Ron Maupin Jan 28 at 14:28
  • 1
    Basically, flow control is controlled by the receiver sending parameters to the sender, while congestion control is controlled by the sender, but not sending parameters to the receiver. – Ron Maupin Jan 28 at 15:18

Not the answer you're looking for? Browse other questions tagged or ask your own question.