BDP Explained: Why a Fast Link Still Feels Slow
The bandwidth-delay product — BDP for short — is how much data has to be in flight, sent but not yet acknowledged, to keep a link completely full. It is simply the link's bandwidth multiplied by the round-trip time, and it explains a puzzle every network engineer meets sooner or later: a fast link that delivers slow transfers. When the TCP window is smaller than the BDP, the sender runs out of permission to send and the link idles between bursts, no matter how fast the link itself is.
The short answer
\nWhat is the bandwidth-delay product? It is bandwidth multiplied by round-trip time: the amount of data that must be in flight — sent, but not yet acknowledged — at any moment to keep a path completely full. Every path has this number whether you compute it or not, and it quietly decides how fast any single transfer on that path can go.
\nTake a modern long-haul path: 100 Gbps of bandwidth and an 80 ms round-trip time. Its BDP is 1 GB — a gigabyte of data must be on the wire at every instant for that link to run at full speed. Now send one ordinary TCP connection down it with a classic 64 KB window, and the transfer runs at about 6.6 Mbps. The link is fine. The sender is simply not allowed to have enough data in flight to fill it, so most of the pipe sits empty most of the time. This article is about that gap — and the three things that close it: a window at least as big as the BDP, window scaling to make such a window legal, and loss low enough that the second ceiling does not take over.
\nThink of the path as a motorway between two cities. Bandwidth is the speed limit combined with the number of lanes: how many cars per hour the road could carry if it were full. Round-trip time is how long the road is, measured as the time a car takes to make the trip and report back. The bandwidth-delay product is the number of cars that must be on the road at the same moment for the road to actually carry traffic at its rated capacity.
\nA short, fast road needs only a few cars on it to look busy. A very long, very fast road needs an enormous number — leave it with only a handful of cars and it looks deserted, however high the speed limit is. A small TCP window is exactly that rule: only a handful of cars allowed on the road at once. Your cars still travel at full speed; there are just never enough of them. The road's capacity is wasted, and your effective speed — cars arriving per hour — collapses.
\nThe formula, worked three ways
\nThe formula is a single multiplication: BDP = bandwidth × RTT. The only skill involved is keeping the units honest — bandwidth in bits per second, RTT in seconds, and the answer comes out in bits; divide by 8 for bytes. Here are three paths worked exactly. The first row is the free calculator's own defaults, linked at the end of this article.
\n| Path | Bandwidth | RTT | BDP in bits | BDP in bytes |
|---|---|---|---|---|
| Calculator defaults | 1 Gbps | 50 ms | 50,000,000 | 6.25 MB |
| Data center | 10 Gbps | 1 ms | 10,000,000 | 1.25 MB |
| Long-haul headline | 100 Gbps | 80 ms | 8,000,000,000 | 1,000 MB (about 954 MiB) |
The headline row, line by line. Bandwidth: 100 Gbps = 100 × 109 bits per second. RTT: 80 ms = 0.080 seconds. Multiply: 100 × 109 × 0.080 = 8 × 109 bits. Convert: 8 × 109 ÷ 8 = 1 × 109 bytes — 1,000 MB, or about 954 MiB (a MiB is 1,048,576 bytes, slightly more than a MB). Counted in ordinary 1,500-byte packets, that is 1,000,000,000 ÷ 1,500 ≈ 666,667 packets in flight at once. That is what \"full\" means on this path: not a burst, but a permanent condition.
\nWhy the window is the ceiling
\nTCP's reliability rule creates the ceiling. A sender may have at most one window of unacknowledged data outstanding; when the window is used up, it must stop and wait. Acknowledgements take one round-trip time to come back, so the fastest a single connection can ever go is throughput ≤ window ÷ RTT — one window per round trip, forever.
\nThe classic window is tiny. In the original TCP design (RFC 793) the window is a 16-bit field in the header, so the largest window a receiver can advertise is 65,535 bytes — call it 64 KB. Now the arithmetic: 65,535 bytes × 8 = 524,280 bits per round trip. On the 80 ms path, 524,280 ÷ 0.080 ≈ 6.6 Mbps. On a 50 ms path, 524,280 ÷ 0.050 ≈ 10.5 Mbps. The link speed does not appear in either sum — a 1 Gbps link and a 100 Gbps link return the same answer.
\nThat is the whole explanation of \"we have a 1 Gbps circuit, but the backup runs at 10 Mbps.\" The sender fires one small window across, then sits idle waiting for permission to send more. The link is busy for a few percent of each round trip and empty for the rest.
\nWindow scaling: removing the 64 KB ceiling
\nThe fix is window scaling (RFC 7323). During connection setup, each side can include a window scale option in its SYN packet carrying a shift count from 0 to 14. From then on, every window value that side advertises is multiplied by 2 raised to the shift — so the maximum possible window becomes 65,535 × 214 = 1,073,725,440 bytes, about 1 GB. The option can only be negotiated in the SYN; a connection that starts without it is stuck at 64 KB for its whole life.
\nHow big a shift does the headline path need? It needs a window of at least 1,000,000,000 bytes, and 1,000,000,000 ÷ 65,535 ≈ 15,259 — so the multiplier must be at least 15,259. A shift of 13 gives 213 = 8,192: not enough. A shift of 14 gives 214 = 16,384: enough. This path needs the maximum shift, with nothing to spare.
\nTwo warnings. Both sides must offer the option — one silent side disables it for the whole connection. And a middlebox that strips TCP options (some firewalls, NATs and proxies do) removes scaling silently, leaving a connection that looks perfectly healthy and still runs at window ÷ RTT. In practice, modern operating systems negotiate scaling and auto-tune their buffers by default, so the real-world fix is usually to check that scaling is on and that no application has pinned a small fixed buffer — not to hand-set one magic number.
\nHere is the same 80 ms path drawn twice — once with a window that covers the BDP, and once with the classic 64 KB window:
\n \nAnd the three worked examples side by side — notice how the data-center path needs almost nothing, while the long-haul path needs nearly a gigabyte:
\n \nLoss: the second ceiling
\nSuppose the window is fixed. A single TCP flow can still be capped — by packet loss. Classic TCP treats a lost packet as the signal to slow down, and in steady state that behaviour has a well-known bound, the Mathis bound. In the simplified form the calculator uses: throughput ≈ MSS in bits ÷ (RTT × √p), where p is the loss rate written as a fraction and √ means square root.
\nWork it with an MSS of 1,460 bytes — 11,680 bits — on the 80 ms path. At 0.1% loss (p = 0.001, √p ≈ 0.0316): 11,680 ÷ (0.080 × 0.0316) ≈ 4.6 Mbps. At 0.01% loss (√p = 0.01): about 14.6 Mbps. At 0.001% loss (√p ≈ 0.00316): about 46 Mbps. Loss rates that look like rounding errors take a fast path down to single-digit megabits.
\nRead this as what it is: an approximate steady-state bound for classic loss-based congestion control — the Reno and CUBIC family, which slows down when it sees loss. Newer BBR-style control models the path's bandwidth and delay directly and does not obey the same bound. And the bound applies per flow: eight parallel streams get eight bounds between them, which is why a multi-stream speed test looks so much faster than the single file copy a user is complaining about.
\nWhen BDP matters — and when it does not
\nInside a data center, RTT is around 1 ms, and at 10 Gbps the BDP is only 1.25 MB. Scaled windows cover that easily and defaults usually cope, so BDP is rarely the problem there. It bites where distance or speed grows: long-haul WAN links, replication between regions, backups sent to another site, satellite paths — anywhere the product of bandwidth and delay gets large. The rule of thumb: the faster and the further, the bigger the BDP, and the more the window decides your throughput.
\nOne honest footnote about other transports. QUIC runs over UDP, but it has its own built-in flow control, and the same in-flight logic applies — its windows must cover the BDP too. Raw UDP has no window at all: nothing stops the sender, and the application itself decides how much to have outstanding, for better or for worse.
\nFour BDP mistakes that actually happen
\n1. Upgrading bandwidth to fix a window problem. A faster link raises the BDP and leaves throughput at window ÷ RTT — exactly where it was. You have bought a wider empty road.
\n2. Testing with a single stream and blaming the link. One flow is bounded by the window and by the loss bound all on its own. A link that \"fails\" a single-stream test may carry an application's many streams perfectly well — test the way the traffic actually flows.
\n3. Pinning small fixed socket buffers. A fixed buffer size set years ago overrides the operating system's auto-tuning and hard-caps the effective window on every connection, forever. It is one of the most common reasons a healthy-looking server is slow across distance.
\n4. Ignoring loss because the interface shows no errors. Interface counters can read zero while queues somewhere upstream drop one packet in a thousand. At 80 ms of RTT that invisible 0.1% bounds a single flow near 4.6 Mbps — the loss does not have to be visible to be decisive.
\nTry it yourself
\nRun the headline example in the free Bandwidth-Delay Product Calculator: set 100 Gbps and 80 ms and it asks for 1,000 MB in flight and window scaling at shift 14; then try its defaults — 1 Gbps, 50 ms, MSS 1,460 bytes — and watch the BDP shrink to 6.25 MB while the loss slider prices what packet loss does to a single flow. To prove the single-stream point on a real path, build the test with the iPerf3 command builder: run one stream, then several in parallel, and compare. And the MSS that feeds the loss bound comes from the MTU/MSS calculator — 1,460 bytes is the answer for ordinary Ethernet; tunnels make it smaller.
\nRelated guides
- BDP = bandwidth × RTT. It is the amount of data that must be unacknowledged and in flight at any instant to keep a path fully used — if less than the BDP is outstanding, some of the link's capacity is going unused.
- The headline example: 100 Gbps × 80 ms = 8 billion bits = 1,000 MB (about 954 MiB) that must be in flight at once — roughly 666,667 packets of 1,500 bytes each, all sent and none of them yet acknowledged.
- A classic unscaled TCP window is at most 65,535 bytes, so it caps throughput at window ÷ RTT: about 6.6 Mbps on an 80 ms path and about 10.5 Mbps on a 50 ms path, whatever the link speed. Window scaling (RFC 7323) raises the maximum window to about 1 GB via a shift count up to 14 — and the 100 Gbps × 80 ms path needs the full shift of 14.
- Loss caps throughput separately, through the Mathis bound (in the simplified form used by the calculator: MSS in bits ÷ (RTT × √loss fraction)): at MSS 1,460 bytes and 80 ms RTT, 0.1% loss bounds a single classic TCP flow near 4.6 Mbps and 0.01% loss near 14.6 Mbps. It is an approximate bound for loss-based congestion control, not a guarantee.