BDP and TCP Window Sizing: Complete Guide to Bandwidth-Delay Product

BDP and TCP Window Sizing: Complete Guide to Bandwidth-Delay Product

Published on June 3, 2026 · Niwo

BDP and TCP Window Sizing: Complete Guide to Bandwidth-Delay Product

What is Bandwidth-Delay Product (BDP)?

Bandwidth-Delay Product (BDP) is a fundamental metric in TCP/IP networking that represents the maximum amount of data that can be “in flight” — transmitted but not yet acknowledged — on a network link at any given time. It is the product of the link’s bandwidth (capacity in bits per second) and its round-trip time (RTT in seconds):

BDP = Bandwidth × RTT

The result is a quantity of data, measured in bits or bytes, that directly determines the minimum TCP window size required to achieve full link utilization. If your TCP window is smaller than the BDP, the sender will run out of data to transmit while waiting for acknowledgments, leaving the link idle and wasting available bandwidth.

Networks where the BDP exceeds 10⁵ bits (12,500 bytes) are classified as Long Fat Networks (LFNs) per RFC 1072. This category includes most modern high-speed connections: gigabit Ethernet, 4G/5G cellular, satellite links, and intercontinental fiber routes.

Why BDP matters for TCP

TCP is a sliding-window protocol. The sender can only transmit up to one window’s worth of data before it must stop and wait for acknowledgments (ACKs). Without a sufficiently large window, the sender cannot keep the pipe full:

  • Window < BDP: The link is underutilized. The sender periodically goes idle waiting for ACKs, reducing effective throughput below the available bandwidth.
  • Window ≥ BDP: The sender can continuously stream data. ACKs arrive just as new data needs to be sent, achieving maximum throughput.

This relationship is the foundation of TCP performance tuning. Every network engineer, DevOps professional, and system administrator who manages high-throughput connections needs to understand BDP to diagnose performance bottlenecks and configure systems correctly.


How TCP Window Size Affects Throughput

The TCP receive window (rwnd) is the amount of data the receiver is willing to accept at any moment. The sender uses the minimum of rwnd and its own congestion window (cwnd) to determine how much data it can transmit before receiving an ACK.

When the window is smaller than the BDP:

Bandwidth: 1 Gbps
RTT: 100 ms
BDP = 1,000,000,000 bps × 0.1 s = 100,000,000 bits = 12.5 MB

Window: 64 KB (default without scaling)
Data in flight: 64 KB
Link utilization: 64 KB / 12,500 KB = 0.5%

The link is idle 99.5% of the time. The sender blasts 64 KB, then waits 100 ms for ACKs, then blasts another 64 KB. This is the single most common cause of poor TCP throughput on high-latency links.

Window too large = congestion

An excessively large window can cause problems too:

  • Bufferbloat: Oversized buffers in routers and switches delay packets unnecessarily, increasing RTT and degrading interactive applications
  • Retransmission storms: If a window is too large relative to the path capacity, a single packet loss can trigger massive retransmissions
  • Peer memory exhaustion: The receiver must allocate buffer space equal to the advertised window

The Goldilocks zone

The optimal TCP window size is equal to or slightly larger than the BDP. At this point:

  • The pipe is always full (maximum theoretical throughput)
  • ACK-clocked pacing keeps bursts manageable
  • A single loss event affects a predictable amount of data

🔢 Calculate the exact optimal window for your network in seconds with our BDP Calculator — enter bandwidth and RTT, and get the recommended TCP buffer sizes instantly.


The BDP Formula Explained

The BDP formula is deceptively simple, but understanding its units is critical:

Step 1: Know your bandwidth in bits per second

Always convert to bits per second before calculating. Common conversions:

Link speedBits per second
100 Mbps100,000,000 bps
1 Gbps1,000,000,000 bps
10 Gbps10,000,000,000 bps
100 Gbps100,000,000,000 bps

Step 2: Measure RTT in seconds

RTT is the time between sending a packet and receiving its acknowledgment. Use ping or mtr to measure baseline RTT. Convert milliseconds to seconds:

  • 50 ms = 0.05 s
  • 100 ms = 0.1 s
  • 300 ms = 0.3 s
  • 600 ms = 0.6 s

Step 3: Multiply and convert to bytes

BDP (bits) = Bandwidth (bps) × RTT (seconds)
BDP (bytes) = BDP (bits) / 8

Real calculation: 1 Gbps at 100 ms RTT

BDP = 1,000,000,000 bps × 0.1 s
    = 100,000,000 bits
    = 12,500,000 bytes
    ≈ 12.5 MB

This means the TCP window must be at least 12.5 MB to fully utilize a 1 Gbps link with 100 ms RTT. The default TCP window of 64 KB (without window scaling) can only fill 0.5% of this pipe.

Quick formula for rough estimates

Forgetting to convert units? Use this simplified version:

BDP (MB) = Bandwidth (Gbps) × RTT (seconds) × 125

Check: 1 Gbps × 0.1 s × 125 = 12.5 MB ✓

Or for bytes directly:

BDP (bytes) = Bandwidth (Mbps) × RTT (ms) × 125

Check: 1,000 Mbps × 100 ms × 125 = 12,500,000 bytes = 12.5 MB ✓


BDP Examples by Scenario

Different network environments produce vastly different BDP values. Here is a representative table across common scenarios:

ScenarioBandwidthRTTBDP (bytes)BDP (human)Min window needed
Gigabit LAN1 Gbps0.5 ms62.5 KB62.5 KB64 KB
Fast LAN100 Mbps1 ms12.5 KB12.5 KB16 KB
DOCSIS Cable200 Mbps20 ms500 KB500 KB512 KB
Residential DSL20 Mbps30 ms75 KB75 KB128 KB
4G/LTE Cellular50 Mbps50 ms312.5 KB312 KB384 KB
5G Cellular500 Mbps15 ms937.5 KB937 KB1 MB
Enterprise WAN100 Mbps80 ms1.0 MB1 MB1 MB
Transcontinental (fiber)1 Gbps150 ms18.75 MB18.75 MB19 MB
Satellite (geostationary)50 Mbps600 ms3.75 MB3.75 MB4 MB
Satellite (Starlink)200 Mbps40 ms1 MB1 MB1 MB
Intercontinental (10G)10 Gbps200 ms250 MB250 MB256 MB
Research (100G, cross-Atlantic)100 Gbps100 ms1.25 GB1.25 GB1.5 GB

🧮 See any scenario that matches your network? Use our BDP Calculator to compute exact values for your specific bandwidth and RTT.

Analysis

  • LAN connections are rarely BDP-constrained — even a modest 64 KB window can saturate a 1 Gbps link with sub-millisecond RTT
  • WAN and intercontinental links are the most BDP-sensitive — a 1 Gbps transatlantic connection needs a ~19 MB window
  • Satellite links combine moderate bandwidth with very high latency, making BDP tuning critical for acceptable performance
  • Cellular networks have moderate BDP values but variable RTT under load, requiring adaptive window sizing
  • High-speed research networks (100 Gbps, 100+ ms RTT) push BDP into gigabytes, requiring careful kernel and hardware tuning

TCP Window Scaling

The original TCP specification (RFC 793, 1981) defined the window field as a 16-bit value, limiting the maximum window to 65,535 bytes (64 KB). This was perfectly adequate for the networks of the early 1980s — links were slow and delays were small.

Why 64 KB isn’t enough

A 64 KB window limits TCP throughput to:

Max throughput = Window / RTT = 65,535 bytes / 0.1 s = 655,350 B/s ≈ 5.2 Mbps

On a modern 1 Gbps link with 100 ms RTT, this means using only 0.5% of available bandwidth. Even on a low-latency 1 Gbps LAN (0.5 ms RTT), a 64 KB window caps throughput at ~1 Gbps — barely enough for a single stream.

RFC 1323: TCP Window Scaling Option

RFC 1323 (1992) introduced the TCP Window Scale option — a three-byte TCP header option that adds a scale factor (shift count) to the window field:

Effective Window = Window Field × 2^Scale Factor

The scale factor (0 to 14) is negotiated during the TCP three-way handshake. Each side advertises its scale factor in the SYN and SYN-ACK segments:

Scale factorMax window
0 (no scaling)64 KB
1128 KB
2256 KB
3512 KB
41 MB
52 MB
64 MB
78 MB
816 MB
932 MB
1064 MB
11128 MB
12256 MB
13512 MB
141 GB

With scaling factor 14, the theoretical maximum window is 1 GB — sufficient for virtually any real-world network.

How to verify window scaling is enabled

On Linux:

# Check if window scaling is enabled
sysctl net.ipv4.tcp_window_scaling

# Should output: net.ipv4.tcp_window_scaling = 1

# Check negotiated scale factor for a connection
ss -ti | grep wscale
# Look for "wscale:7,7" in the output

On macOS:

# Window scaling is enabled by default since OS X Mavericks
sysctl net.inet.tcp.win_scale_factor

On Windows:

# Check current setting
netsh interface tcp show global
# Look for "Receive Window Auto-Tuning Level"

# Window scaling is auto-negotiated by default in modern Windows 10/11

TCP auto-tuning in modern OS

Modern operating systems perform automatic TCP buffer tuning:

  • Linux (since kernel 2.6.7): The kernel automatically adjusts tcp_rmem and tcp_wmem based on connection RTT and observed throughput. Socket buffers grow dynamically up to tcp_rmem[2] (max).
  • Windows (since Vista/2008): “Receive Window Auto-Tuning” adjusts the window size per-connection based on RTT and packet loss. This is enabled by default in Windows 10/11.
  • macOS (since Mavericks): Auto-tuning is enabled by default.

In most cases, auto-tuning works well. Exceptions include:

  • Extremely high BDP links (100 Gbps research networks)
  • Satellite links with high RTT variability
  • Environments with aggressive packet shaping or QoS policies
  • Virtualized environments with para-virtualized NIC drivers

How to Calculate Optimal TCP Window

The optimal TCP window size ensures the sender can keep the link saturated without overwhelming the receiver. Here is the step-by-step process:

Formula

Optimal Window (bytes) = Bandwidth (bps) × RTT (seconds) / 8

Add a small safety margin (10–25%) to account for RTT jitter, ACK compression, and TCP overhead:

Recommended Window = Optimal Window × 1.25
Optimal Window = 1,000,000,000 × 0.08 / 8
               = 10,000,000 bytes ≈ 10 MB

Recommended = 10 MB × 1.25 = 12.5 MB

On Linux, configure:

# Set max receive buffer to 12.5 MB (13,107,200 bytes)
echo 13107200 > /proc/sys/net/core/rmem_max

# Set TCP receive buffer auto-tuning range
echo "4096 87380 13107200" > /proc/sys/net/ipv4/tcp_rmem
Optimal Window = 10,000,000,000 × 0.18 / 8
               = 225,000,000 bytes = 225 MB

Recommended = 225 MB × 1.25 = 281.25 MB

On Linux, configure:

# Set max receive buffer to 300 MB
echo 314572800 > /proc/sys/net/core/rmem_max

# Set TCP receive buffer range
echo "4096 87380 314572800" > /proc/sys/net/ipv4/tcp_rmem

# IMPORTANT: Verify jumbo frames are enabled on the NIC
# Without jumbo frames (9000 MTU), CPU overhead can limit throughput

Example 3: 4G LTE with 50 ms RTT and 50 Mbps

Optimal Window = 50,000,000 × 0.05 / 8
               = 312,500 bytes ≈ 312 KB

Recommended = 312 KB × 1.25 ≈ 390 KB
echo "4096 87380 400000" > /proc/sys/net/ipv4/tcp_rmem
Optimal Window = 200,000,000 × 0.04 / 8
               = 1,000,000 bytes ≈ 1 MB
echo "4096 87380 1048576" > /proc/sys/net/ipv4/tcp_rmem

🎯 Calculate your exact numbers: BDP Calculator — just enter bandwidth and RTT to get the precise buffer sizes you need.


Linux TCP Tuning

Linux offers extensive TCP tuning through sysctl parameters under /proc/sys/net/ipv4/. Here are the most important settings for BDP and window sizing:

Key sysctl parameters

ParameterDescriptionDefaultBDP-optimized
net.ipv4.tcp_window_scalingEnable RFC 1323 window scaling11 (must be on)
net.ipv4.tcp_rmemTCP receive buffer (min, default, max in bytes)4096 131072 62914564096 87380 <BDP_bytes>
net.ipv4.tcp_wmemTCP send buffer (min, default, max in bytes)4096 16384 41943044096 65536 <BDP_bytes>
net.core.rmem_maxMax OS receive buffer212992BDP × 1.5
net.core.wmem_maxMax OS send buffer212992BDP × 1.5
net.ipv4.tcp_moderate_rcvbufAuto-tuning of receive buffer11 (leave on)
net.ipv4.tcp_congestion_controlCongestion control algorithmcubicbbr (for high BDP)
net.core.netdev_max_backlogMax packets queued on input10005000–50000 (high BDP)
net.ipv4.tcp_slow_start_after_idleReset cwnd after idle10 (avoid slow start penalty)
net.ipv4.tcp_mtu_probingEnable MTU probing01 (detect path MTU)

Create /etc/sysctl.d/99-bdp-tuning.conf:

# BDP-optimized TCP settings for high-latency/high-bandwidth links

# RFC 1323 window scaling (must be on)
net.ipv4.tcp_window_scaling = 1

# Allow oversized windows for >1 Gbps links
# Adjust these values based on your specific BDP calculation
net.core.rmem_max = 134217728    # 128 MB
net.core.wmem_max = 134217728    # 128 MB

# TCP auto-tuning buffer ranges: min default max
net.ipv4.tcp_rmem = 4096 87380 134217728
net.ipv4.tcp_wmem = 4096 65536 134217728

# Enable BBR congestion control (kernel 4.9+)
net.ipv4.tcp_congestion_control = bbr

# Increase backlog for high-throughput NICs
net.core.netdev_max_backlog = 50000

# Don't reset congestion window after idle
net.ipv4.tcp_slow_start_after_idle = 0

# Enable MTU probing
net.ipv4.tcp_mtu_probing = 1

# Increase max orphaned connections
net.ipv4.tcp_max_orphans = 65536

# TCP Fast Open (RFC 7413)
net.ipv4.tcp_fastopen = 3

# Enable SACK and selective ACKs
net.ipv4.tcp_sack = 1
net.ipv4.tcp_dsack = 1

Apply immediately:

sysctl -p /etc/sysctl.d/99-bdp-tuning.conf

Verify your settings are working

# Check current buffer sizes per connection
ss -ti | head -20

# Look for "rtt:" and "cwnd:" to see actual RTT and congestion window
# Example output:
# ESTAB    0      0      10.0.0.1:443     10.0.0.2:54321
#          cubic wscale:7,7 rtt:42.5/7.5 cwnd:1890 ssthresh:1890

# Monitor throughput with nload or iperf3
iperf3 -c server.example.com -t 30

Important considerations

  • Buffer size ≠ window immediately: TCP auto-tuning grows buffers gradually. Use iperf3 with multiple parallel streams if single-stream throughput is still low.
  • If you change tcp_rmem, you must also increase rmem_max: TCP will not exceed rmem_max regardless of what tcp_rmem[2] says.
  • BBR vs Cubic: For high-BDP links, BBR (Bottleneck Bandwidth and RTT) typically outperforms Cubic by avoiding unnecessary packet loss. BBR is available in Linux kernels 4.9+.
  • Jumbo frames: Enable 9000-byte MTU on your NIC and switch infrastructure. Larger frames reduce CPU overhead per byte and improve TCP efficiency at high throughput.
  • Tune at the right layer: Application socket buffers (SO_RCVBUF, SO_SNDBUF) override kernel defaults. Check with ss -tm for per-socket buffer allocation.

Frequently Asked Questions

What is a good TCP window size?

A good TCP window size is equal to or slightly larger than the Bandwidth-Delay Product (BDP) for your link. In practice, add 10–25% headroom above the calculated BDP to account for RTT jitter and TCP overhead. For example, if your BDP is 10 MB, set your TCP buffer maximum to 12.5 MB. The exact value depends on your bandwidth and latency — use our BDP Calculator to get your precise number.

How to calculate BDP?

BDP = Bandwidth (bps) × RTT (seconds). Convert bandwidth to bits per second and RTT to seconds, then multiply. Divide by 8 to get bytes. Example: 1 Gbps × 0.1 s = 100,000,000 bits = 12.5 MB. This tells you the minimum TCP window needed to fully utilize the link.

What is TCP window scaling?

TCP window scaling is an extension (RFC 1323) that allows TCP windows larger than the default 65,535 bytes. It adds a shift count factor (0–14) negotiated during the TCP handshake, enabling windows up to 1 GB. Without window scaling, a TCP connection can only achieve ~5.2 Mbps on a 100 ms RTT link, regardless of available bandwidth.

What is the TCP throughput formula?

The theoretical maximum TCP throughput is:

TCP Throughput = TCP Window / RTT

For example, with a 64 KB window and 100 ms RTT: 65,535 bytes × 8 / 0.1 s = 5.24 Mbps. With a 12.5 MB window (optimal for 1 Gbps / 100 ms RTT): ~12,500,000 bytes × 8 / 0.1 s = 1 Gbps. Actual throughput is always lower due to congestion, packet loss, protocol overhead, and the congestion control algorithm in use.

How to check TCP window size in Linux?

Use the ss command to inspect TCP socket details:

# Show TCP sockets with window info
ss -ti | less

# For a specific connection
ss -ti 'src 10.0.0.1:443'

# Look for "wscale:" (scale factor), "cwnd:" (congestion window), and "rtt:"
# ss also shows the recv-q and send-q sizes

To check system-wide buffer limits:

sysctl net.ipv4.tcp_rmem
sysctl net.ipv4.tcp_wmem
sysctl net.core.rmem_max

The output tcp_rmem = 4096 87380 6291456 means minimum 4 KB, default 87 KB, maximum 6 MB per socket.

Does BDP apply to UDP?

Strictly speaking, BDP is a link property independent of the transport protocol. However, UDP applications don’t have a built-in window mechanism — the application itself must implement flow control. For real-time UDP applications (VoIP, video streaming), BDP matters for jitter buffer sizing rather than window sizing. For reliable UDP protocols like QUIC (which runs on top of UDP), BDP is equally important as it uses similar congestion control and windowing mechanisms to TCP.

What happens if my window is larger than BDP?

A window slightly larger than BDP is fine and even desirable (10–25% headroom). However, a window significantly larger than BDP can lead to:

  • Bufferbloat: Data accumulates in router queues, increasing latency for all flows
  • Retransmission storms: If packet loss occurs, the sender retransmits a huge amount of data
  • Receiver memory exhaustion: The receiving application must allocate buffers equal to the advertised window

The goal is to match the window to the BDP plus a reasonable safety margin.


Conclusion

Bandwidth-Delay Product is one of the most important concepts for understanding and optimizing TCP throughput. Whether you are debugging slow file transfers across a WAN, tuning a satellite link, or designing a high-performance research network, BDP tells you the single most important number: how big your TCP window needs to be.

Key takeaways

  • BDP = Bandwidth × RTT: This simple formula determines the minimum TCP window size required for full link utilization
  • Default 64 KB windows are useless on modern networks: Without window scaling (RFC 1323), you cannot exceed ~5 Mbps on a 100 ms RTT link
  • Linux auto-tuning works well for most cases, but extreme BDP links (1 Gbps, 100+ ms RTT) benefit from manual tuning
  • BBR congestion control significantly outperforms Cubic on high-BDP paths
  • Window scaling is mandatory: Verify it is enabled on all systems handling high-throughput traffic

Put this knowledge to work

  1. Calculate your BDP — Use our BDP Calculator to compute the optimal window size for your specific bandwidth and RTT
  2. Tune your Linux systems — Apply the sysctl configuration in this guide and verify with iperf3
  3. Monitor — Track per-connection RTT, window utilization, and throughput to validate your tuning
  4. Iterate — Network conditions change. Revisit your BDP calculation when you upgrade bandwidth or change providers

Understanding BDP separates novice network administration from professional-grade performance engineering. Master it, and you will never leave throughput on the table again.

Related articles