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
2. TCP parameters — defaults follow RFC 6928 and a 1500-byte MTU
3. Result
- First-flight capacity (initcwnd × MSS)0 B
- Payload on the wire0 B
- Handshake cost0 RTT / 0 ms
- Slow-start transfer time0 ms
- Bandwidth-delay product (BDP)0 B
- Closed-form round trips0
- Round trips actually simulated0
- Average throughput achieved0 Mbps
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
- Shrink the payload to fit the first flight—
- Raise initcwnd to 20 segments—
- Reuse a warm connection (skip the handshake)—
- Halve the RTT (move closer / use an edge)—
- Crossover payload — where bandwidth finally dominates—
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:
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:
With the defaults that produces a ladder worth memorising:
- 1 round trip — 14,600 bytes (14.3 KiB)
- 2 round trips — 43,800 bytes (42.8 KiB)
- 3 round trips — 102,200 bytes (99.8 KiB)
- 4 round trips — 219,000 bytes (213.9 KiB)
- 5 round trips — 452,600 bytes (442.0 KiB)
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:
- Warm connection — 0 RTT. The socket is open and the window may already be large.
- TCP three-way handshake — 1 RTT. SYN, SYN-ACK, then the request rides with the ACK.
- TLS 1.3 full handshake — 1 additional RTT, so 2 RTT cold.
- TLS 1.2 full handshake — 2 additional RTT, so 3 RTT cold.
- TLS 1.3 session resumption with 0-RTT early data — 0 additional RTT, so 1 RTT cold. The request travels with the ClientHello, at the cost of replay exposure, which is why it is only safe for idempotent requests.
- QUIC / HTTP-3 — 1 RTT on a first connection because the transport and cryptographic handshakes are combined, and 0 RTT on resumption. QUIC uses the same 10-segment initial window: RFC 9002 sets it to
min(10 × max_datagram_size, max(14720, 2 × max_datagram_size)).
Step 5 — latency-bound or bandwidth-bound
The bandwidth-delay product is how many bytes fit in the pipe at once:
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).
What this deliberately does not model
- Packet loss. A single loss triggers fast retransmit or, worse, a retransmission timeout of at least 200 ms on Linux, which dwarfs everything computed here. This is a clean-path model.
- Server think time. Time to first byte also contains backend processing. Add it separately.
- DNS and connection setup discovery. A cold DNS lookup is typically one further RTT to the resolver, sometimes several.
- Protocol overhead inside the first flight. HTTP response headers, HTTP/2 HEADERS frames and TLS record framing (roughly 22 to 29 bytes per record) all consume part of the 14,600 bytes. Budget around 13.5 KiB of actual HTML if you want to be sure, not 14.6 KB.
- BBR and other pacing algorithms. Slow start behaviour is the same at the start, but the exit conditions and the steady-state rate differ from classic loss-based CUBIC.
- Connection warmth carried over. A reused connection often has a window far above initcwnd, so warm mode here is a conservative estimate: it uses the initial window rather than a grown one.
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:
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
Last updated 29 July 2026