Frontend Labs
⋯

2. Network Fundamentals That Determine Performance

2.1 TCP handshake and connection reuse cost

A cold TCP connection costs 1 RTT before any bytes of your protocol move. Add TLS 1.2 (2 RTT) or TLS 1.3 (1 RTT, 0-RTT for resumption) and a client hitting a fresh connection per request pays 2-3 RTTs of pure overhead. This is why connection pooling / keep-alive is the single highest-leverage performance change most APIs can make.

Fresh HTTPS/TLS1.2 connection over a 50ms RTT link:
  TCP handshake:   50ms
  TLS handshake:  100ms
  HTTP request:    50ms
  ---------------------
  Total before first byte: 200ms

Reused (keep-alive) connection, same link:
  HTTP request: 50ms   (4x faster, purely from reuse)

2.2 DNS

DNS resolution is often the invisible tail-latency source. A misconfigured resolver, or a client re-resolving on every connection because it ignores TTLs (or a service mesh sidecar doing DNS on every call), silently adds 20-200ms. Under load tests, always resolve DNS once and reuse the IP, unless you're specifically testing DNS behavior (e.g., DNS-based failover, GSLB).

2.3 TCP congestion control & the bandwidth-delay product

Throughput is capped by:

Throughput <= TCP_window_size / RTT

This is why a single TCP connection between two data centers 150ms apart, even on a 10 Gbps link, may only push a few Mbps until the congestion window grows (slow start) or unless you use multiple parallel streams (HTTP/2 multiplexing, multiple connections). This matters directly for load tests: if your load generator opens too few connections over a high-latency link, you will bottleneck the generator, not the server under test.

2.4 Nagle's algorithm & delayed ACK

Nagle's algorithm batches small writes; delayed ACK delays acknowledgments up to ~40ms waiting to piggyback data. Combined, they can produce a notorious ~40ms stall on small, latency-sensitive request/response protocols. Fix: disable Nagle (TCP_NODELAY) on latency-sensitive services — virtually every HTTP server and load tool does this by default, but hand-rolled TCP clients (see the C example in §9.1) must set it explicitly.

2.5 HTTP/1.1 vs HTTP/2 vs HTTP/3

Multiplexing Head-of-line blocking Handshake Best for
HTTP/1.1 No (needs 6 conns/host) Yes, per-connection TCP+TLS legacy, simple
HTTP/2 Yes, single TCP conn Yes, at TCP layer (packet loss stalls all streams) TCP+TLS most APIs today
HTTP/3 (QUIC) Yes, per-stream, over UDP No (independent streams) 1-RTT / 0-RTT mobile/lossy networks

Load testing implication: benchmarking an HTTP/2 API from a client that only opens HTTP/1.1 connections will radically understate real client concurrency behavior (a browser reuses one HTTP/2 connection for 100 requests; your tool must be configured to do the same, or configured to open many connections if you're modeling many distinct clients).

2.6 MTU, fragmentation, and packet loss

Standard Ethernet MTU is 1500 bytes. Large JSON/gRPC payloads that exceed the path MTU get fragmented at the IP layer (or segmented at TCP layer, which is normal and fine) — but on paths with a broken PMTU (common with some VPNs/tunnels), fragmented packets get silently dropped, producing intermittent hangs that look like "random" latency spikes. This is a classic hard-to-diagnose production incident — worth explicitly testing with ping -s 1472 -M do <host> to check for PMTU blackholes before blaming the application.


Generated from real-life-scale-guide.md · 8 Oct 2026 16:36