TCP Slow Start Round-Trip Calculator

Bandwidth-only math says a 100 KB response takes 8 ms on a 100 Mbps link. TCP says it takes three round trips. This tool simulates congestion-window growth flight by flight, tells you whether your payload fits the 14,600-byte first flight, and shows exactly where the time actually goes. Runs entirely in your browser.

1. Network — pick a preset or type your own

One full there-and-back on the path
Decimal Mbps: 1 Mbps = 1,000,000 bit/s
Compressed bytes on the wire, 1 KB = 1024 B

2. TCP parameters — defaults follow RFC 6928 and a 1500-byte MTU

RFC 6928 default: 10
1500 MTU − 20 IPv4 − 20 TCP = 1460
Delayed ACKs are the common real case
DNS lookup is not included
Linux tcp_rmem max default is 6 MB
Used for the savings estimate below
Everything else stays identical

3. Result

0
Data round trips
slow start
0 ms
Total time
handshake + transfer
0 ms
Bandwidth-only guess
payload / bandwidth
0x
Understated by
real / naive
latency-bound
Enter your numbers above.
0 ms 0 ms
Handshake Window-limited flight (idle waiting for ACKs) Bandwidth-limited flight (pipe full)
First flight budget0 / 0 B

4. Round-trip by round-trip

RT cwnd (segments) Usable segments Bytes this flight Cumulative Cost (ms) Elapsed (ms) Limiter

Elapsed includes the handshake. A flight is window-limited when it drains in less than one RTT, so the sender sits idle waiting for acknowledgements; it is bandwidth-limited once the flight takes longer than an RTT to serialise, at which point the pipe is full and slow start no longer matters.

5. What would actually help

The method, exactly

TCP does not start at full speed. A brand-new connection has no idea what the path can carry, so it begins with a small initial congestion window and probes upward. Every calculation on this page follows from that one fact.

Step 1 — the first flight, and where 14 KB comes from

RFC 6928 (2013) raised the recommended initial window from the RFC 5681 rule of min(4×MSS, max(2×MSS, 4380)) to a flat 10 segments. On a standard 1500-byte Ethernet MTU, a TCP segment carries 1500 − 20 (IPv4) − 20 (TCP) = 1460 bytes of payload. So:

firstFlight = initcwnd × MSS = 10 × 1460 = 14,600 bytes (14.26 KiB)

That is the entire budget a server has before it must stop and wait a full round trip for an acknowledgement. This is the real origin of the "keep your critical HTML under 14 KB" advice. It is not a rendering rule or a Google rule; it is an arithmetic consequence of two constants.

Step 2 — exponential growth and the round-trip count

During slow start the sender adds one MSS to the window for every segment acknowledged, which doubles the window each round trip. The window after n round trips, and the cumulative bytes deliverable after k round trips, are a geometric series:

window(n) = initcwnd × g^n segments cumulative(k) = MSS × initcwnd × (g^k − 1) / (g − 1) bytes with g = 2: cumulative(k) = MSS × initcwnd × (2^k − 1) k = ceil( log(1 + payload × (g−1) / (MSS × initcwnd)) / log(g) )

With the defaults that produces a ladder worth memorising:

Crossing one of those boundaries by a single byte costs a full RTT. That is why a 15 KB HTML document can be measurably slower than a 14 KB one on a high-latency connection, and why the gap widens as RTT grows rather than shrinking as bandwidth grows.

Step 3 — the growth factor is rarely a clean 2.0

Slow start grows by one MSS per acknowledgement, not per segment. Most receivers implement delayed acknowledgements and send one ACK for every two segments, so the effective growth is nearer 1.5x per round trip. The growth selector above switches between the textbook 2.0x and the pessimistic 1.5x so you can bracket reality rather than guess it.

Step 4 — the handshake tax

Before a single byte of response can move, the connection has to exist. These costs are additive round trips on top of the data round trips:

Step 5 — latency-bound or bandwidth-bound

The bandwidth-delay product is how many bytes fit in the pipe at once:

BDP = bandwidth (bit/s) × RTT (s) / 8 bytes

If your payload is smaller than the BDP, the connection never fills the pipe and the transfer is latency-bound: buying bandwidth changes nothing, and the only levers are fewer round trips, a shorter RTT, or a smaller payload. A 100 Mbps link at 40 ms RTT has a BDP of 500,000 bytes, which is larger than almost every HTML document, stylesheet and script bundle on the web. This is the single most common reason a bandwidth upgrade does not make a site feel faster.

The timing model this page uses

Each round trip is charged at max(RTT, flightBytes / bandwidth). Below the crossover the sender transmits its window and then idles until the ACKs come back, so the cost is one RTT; above it, the flight takes longer to serialise than an RTT, acknowledgements return while data is still being sent, transmission becomes continuous and the cost is pure serialisation. The window is additionally capped by the receiver window, since a sender may never have more unacknowledged data in flight than min(cwnd, rwnd).

totalTime = handshakeRTTs × RTT + Σ over flights of max(RTT, flightBytes / bandwidth)

What this deliberately does not model

How to check your own numbers

On a Linux server, inspect the live congestion window and smoothed RTT of active sockets, then raise the initial window per route if the data justifies it:

ss -ti # look for cwnd: and rtt: on each socket ip route show # current route attributes ip route change default via 192.0.2.1 dev eth0 initcwnd 20 initrwnd 20

Raising initcwnd is a real lever with a real risk: a larger unacknowledged burst is more likely to overflow a shallow buffer somewhere on a constrained last mile, and the resulting timeout costs far more than the round trip you saved. Measure on the networks your users actually have.

Frequently asked questions

Is the 14 KB limit 14,000 or 14,336 bytes?
Neither, strictly. It is 10 segments of 1460 bytes, which is 14,600 bytes, or 14.26 KiB. The "14 KB" shorthand rounds down and happens to leave a small safety margin for the response headers and TLS record overhead that share the flight. If you tunnel over IPv6 the header is 40 bytes rather than 20, so the MSS drops to 1440 and the budget falls to 14,400 bytes; with the TCP timestamp option enabled it drops another 12 bytes per segment.
Does gzip or Brotli change the round-trip count?
Yes, and it is usually the cheapest fix available. Slow start counts bytes on the wire, so compression works directly on the quantity that matters. A 40 KB HTML document that Brotli compresses to 9 KB moves from two data round trips to one, saving a full RTT on every cold request. This is also why compressing tiny responses still matters at high latency even when the byte saving looks trivial.
Why does my CDN help so much more than my bandwidth upgrade?
Because a CDN edge attacks the term that dominates. Every round trip in the model is multiplied by RTT, so cutting RTT from 120 ms to 15 ms cuts the handshake and every slow-start flight by the same factor of eight. Bandwidth only appears in the serialisation term, which for a sub-BDP payload is never the binding constraint. Turn on compare mode above to see the two paths side by side with your own numbers.
Do HTTP/2 and HTTP/3 remove the slow-start problem?
They remove the per-resource handshake problem, not the congestion-window problem. Multiplexing means many resources share one connection and one window, so the first flight is shared rather than duplicated, which is a large win over HTTP/1.1 with six connections each running its own slow start. But the window still starts at ten segments and still doubles once per round trip. HTTP/3 additionally removes head-of-line blocking at the transport layer and saves a round trip on connection setup.
Should I inline critical CSS to stay under the first flight?
Inlining converts a second request, with its own round trip, into extra bytes in the first document. That is a win only while the combined document still fits inside the first flight, or at least does not push you across a round-trip boundary. Past that point you have paid the same round trip you were trying to avoid and made the document uncacheable. Compute both sizes here before deciding.
Why does the tool sometimes report fewer round trips than the closed form?
The closed form assumes an unbounded window and infinite bandwidth. The simulation additionally caps each flight at the receiver window and charges serialisation time when a flight takes longer than an RTT to send. Once a flight becomes bandwidth-limited the connection is effectively at line rate and the remaining bytes are charged at the serialisation rate rather than at whole round trips, so the two figures diverge for large payloads on slow links.

Michael Lip builds developer tools at Zovo. This calculator implements the RFC 6928 initial window and the classic slow-start geometric series directly, with no fitted constants, so every figure it reports can be reproduced by hand from the formulas above.

Last updated 29 July 2026

By the same builder: GitHub — theluckystrike BeLikeNative — Grammar AI EarlyThunder — Dev Blog Zovo — AI Dev Tools