QA Interview Hub · Knowledge base · Quizzes

Networking

HTTP versions and infrastructure

HTTP/1.1, HTTP/2 and HTTP/3: what changed

HTTP/1.1 is a text protocol over TCP. Main traits:

  • Keep-alive (the default): one TCP connection serves many requests so the handshake is not repeated. It can be closed with the Connection: close header;
  • Head-of-line blocking (HOL): requests on a connection go one after another, a slow response blocks the following ones. Pipelining is not used in practice. Workaround: a browser opens up to ~6 parallel connections per host, and developers once "sharded" domains and bundled files.

HTTP/2 keeps the semantics (methods, codes, headers) but changes the transport:

  • Binary frames and multiplexing: many streams (requests) at once in one connection, responses are interleaved. Domain sharding and file bundling become unnecessary;
  • HPACK: header compression with a shared table (cookies and User-Agent are not sent in full every time);
  • stream priorities; server push is effectively retired (Chrome removed it);
  • in practice only over TLS (ALPN h2).

The problem: HTTP/2 still runs on a single TCP connection, so the loss of one packet stalls all streams (HOL blocking at the TCP level). On bad networks HTTP/2 can be worse than several HTTP/1.1 connections.

HTTP/3 runs over QUIC (UDP, usually port 443). QUIC implements reliability, multiplexing and TLS 1.3 in the protocol itself: a lost packet affects only its own stream; connection setup takes 1 RTT (0-RTT on resumption); connection migration between networks (Wi-Fi → mobile) without a drop; headers are compressed with QPACK. The browser learns about HTTP/3 from Alt-Svc or the HTTPS DNS record; if UDP is blocked, it falls back to HTTP/2.

For QA: the Protocol column in DevTools (http/1.1, h2, h3); curl -v --http2 URL (--http3 only in curl builds that support it); API semantics and test cases do not depend on the version, while performance, behavior under loss and lowercase header names (h2) do.

Proxies, load balancers, CDNs and timeouts

There is rarely a direct connection between a browser and the application. Every hop is a potential source of odd errors, so QA should know what they do.

  • A forward proxy is on the client side (a corporate exit to the internet, Charles, mitmproxy). A reverse proxy is on the server side (nginx, Envoy): it terminates TLS, serves static files, routes to services and compresses responses;
  • A load balancer: L4 works with TCP connections (fast, does not see HTTP), L7 understands HTTP and routes by host, path or headers. Algorithms: round-robin, least connections. A health check removes unhealthy instances; sticky sessions bind a client to an instance;
  • A CDN caches responses at the "edge" closer to the user and offloads the origin. Cache bugs (a stale file, someone else's personalized response) are handled with Cache-Control, Vary, versions in file names, invalidation;
  • Proxy headers: X-Forwarded-For (the real client IP, can be forged by the client), X-Forwarded-Proto, the standardized Forwarded. If an application does not trust the proxy, it sees the balancer's IP and rate limiting fires for everyone together.

Timeouts exist at every step, and the smallest one wins:

  • connect timeout: how long to wait for TCP to be established;
  • read/response timeout: how long to wait for data from the server;
  • the idle timeout on a balancer (often 60 seconds): a connection with no traffic is closed. It "kills" long requests with no response and WebSockets without ping;
  • the client timeout (fetch has none by itself, you need AbortSignal.timeout(ms)), the test timeout and the CI step timeout.

The symptom "a request returns 504 after exactly 60 seconds" almost always matches an idle/proxy timeout, not random slowness. A test with a 30 s timeout fails before the proxy returns 504, and the diagnosis looks different.