Course outline

Networking / Advanced: policy, evidence, capacity, and resilient design / Lesson 17

Distinguish capacity, delay, goodput, and queue pressure

Use explicit units and bounded offline models to reason about bottlenecks without generating load or prescribing universal tuning.

About 5 min readContent reviewed
On this page

Lesson goals

  • Separate link capacity, available capacity, throughput, and application goodput.
  • Calculate a bandwidth-delay budget and a bounded queue conservation model.

Define what the rate counts

A linkโ€™s nominal bit rate is not the same as available capacity for one flow or useful application goodput. Framing, protocol headers, acknowledgments, retransmissions, competing traffic, and endpoint processing consume resources. The common word bandwidth is ambiguous unless the measurement is defined. Label bits versus bytes, decimal versus binary units, time interval, direction, and protocol boundary. A large file-transfer average can hide short congestion bursts or poor interactive latency. Compare measurements only when they count compatible quantities over a relevant and clearly stated interval.

RTT includes more than propagation

Round-trip time can include propagation, serialization, queueing, and endpoint processing between the chosen events. A longer physical path and a growing queue can both increase it, but call for different remedies. One-way delay is not automatically half the RTT because paths and processing can be asymmetric. Establish a baseline and distinguish steady load from bursts before interpreting changes. A single low sample does not characterize tail behavior, and a tiny synthetic sample cannot support a confident production percentile. Retain measurement method and uncertainty alongside the number.

A bandwidth-delay product is a model input, not a tuning command

Multiplying a rate by an RTT gives an amount of in-flight data in a simplified model. A flow limited to a smaller outstanding byte window can have a lower window-only throughput ceiling. Actual TCP behavior also depends on congestion control, receive window, losses, application behavior, and processing. The code below uses decimal bits per second and an explicitly declared forty-millisecond RTT. It changes no socket buffers. Applying a larger window everywhere can consume memory or increase queueing without repairing the actual bottleneck.

python Calculate declared in-flight and window budgets
rate_bps = 50_000_000
rtt_ms = 40
window_bytes = 64_000
bdp_bytes = rate_bps * rtt_ms // (8 * 1000)
window_ceiling_mbps = window_bytes * 8 / (rtt_ms / 1000) / 1_000_000
print(f'bdp_bytes={bdp_bytes}')
print(f'window_only_ceiling_mbps={window_ceiling_mbps:.1f}')
Expected output
bdp_bytes=250000
window_only_ceiling_mbps=12.8

The assumptions produce 250000 bytes of modeled in-flight data and a window ceiling of 12.8 Mbit/s. The window is 64000 decimal bytes. These arithmetic bounds do not measure a path, guarantee throughput, or recommend changing any hostโ€™s transport settings.

Buffering cannot create service capacity

A queue can absorb a burst when arrivals temporarily exceed service, but sustained overload needs capacity, traffic control, or reduced demand. More buffering may retain packets longer while increasing delay. Scheduling and active queue management address different aspects of waiting and congestion feedback. The fixture uses four abstract ticks, bounded arrivals, arrival-before-service ordering, and one fixed-size packet unit. It deliberately omits real packet sizes, multiple queues, retransmissions, and adaptive senders. Conservation makes its limits explicit: arrived units must equal served, dropped, and still-queued units.

python Run a four-tick queue model without traffic
arrivals = [4, 14, 2, 8]
buffer_limit, service_limit = 10, 5
queued = served = dropped = 0
for count in arrivals:
    assert 0 <= count <= 100
    dropped += max(0, queued + count - buffer_limit)
    queued = min(buffer_limit, queued + count)
    departing = min(service_limit, queued)
    served += departing
    queued -= departing
assert sum(arrivals) == served + dropped + queued
print(f'arrived={sum(arrivals)} served={served} dropped={dropped} queued={queued}')
Expected output
arrived=28 served=19 dropped=4 queued=5

The fixture admits 28 arriving units, serves 19, drops 4, and retains 5. All work is bounded and in memory. A tick has no claimed duration, and the output is not a router benchmark, actual loss counter, or prediction of a production queue discipline.

Size for requirements and degraded operation

Capacity planning includes workload mix, burst duration, concurrency, acceptable tail delay, dependency behavior, growth, and remaining service after a stated failure. Two links do not provide twice the usable capacity when they share a smaller upstream bottleneck. A useful investigation distinguishes path pressure from endpoint CPU, storage, or application limits. Offline models help expose assumptions before a separately authorized measurement plan is designed. They do not authorize throughput tests, sustained traffic, scans, interface tuning, or load generation; no such action occurs in this lesson.

Common errors and fixes

Megabits and megabytes are compared as identical units

Why it happens
Rate and data-size units were omitted or converted inconsistently.
How to fix it
Normalize bit and byte units and state the measurement interval explicitly.
Prevent it next time
Include units in variables, labels, and acceptance criteria.

A larger buffer is called an increase in link capacity

Why it happens
Storage for waiting traffic was confused with the service rate.
How to fix it
Evaluate delay, loss, service capacity, and offered demand separately.
Prevent it next time
Review queue conservation and latency, not only drop totals.

A BDP calculation becomes a universal host setting

Why it happens
A simplified in-flight model was mistaken for measured transport requirements.
How to fix it
Identify the actual limiting factor and relevant transport behavior before tuning.
Prevent it next time
Keep arithmetic assumptions separate from authorized operational changes.

Check your understanding

1. What changes if the queue buffer increases to 20 with the same arrivals?

Show worked solution

The same four-tick model serves 19 units, drops none, and retains 9. Removing the four drops did not increase service during the interval; those units remain waiting. The design must consider their delay and later workload rather than calling fewer drops proof of a faster link.

2. Why can a nominal 50 Mbit/s path deliver less application goodput?

Show worked solution

Protocol overhead, competing traffic, window and congestion limits, loss recovery, and endpoints can all consume or limit the useful rate. Define the counted application bytes and interval, then distinguish these causes with appropriate evidence. Nominal capacity alone is not an application throughput promise.

Key takeaways

  • Label rate, delay, and byte boundaries before comparing performance.
  • Use bounded models to question assumptions, not to prescribe universal tuning.

Official references