awesome-everything RU
↑ Back to the climb

Networking & Protocols

HTTP design: priorities, WebTransport, and semantic correctness

Crux RFC 9218 extensible priorities replace HTTP/2''''s broken dependency trees; MASQUE and WebTransport extend QUIC beyond request-response; semantic correctness — right status codes, right Vary, right CORS — is where CDN and caching bugs hide.
Your altitude — climbing toward senior
ZeroJuniorMiddleSenior
You are at senior altitude — in orbit
◷ 16 min

HTTP multiplexes streams. But without priorities, the server streams them in arrival order — which may put a low-priority image before the blocking CSS that pauses rendering. RFC 9218 replaces HTTP/2’s abandoned priority tree with a two-field urgency signal. Meanwhile, WebTransport turns the QUIC connection into a general-purpose bidirectional tunnel — and semantic mistakes in status codes and Vary headers quietly break CDN caching for millions of users.

RFC 9218: Extensible Priorities

HTTP/2’s original priority scheme (dependency trees with weights, RFC 7540 § 5) was complex and poorly implemented. Browsers and servers disagreed on interpretation — Cloudflare reported that in some deployments, priorities made performance worse than no priorities at all, because mismatched implementations caused servers to delay high-priority streams while serving junk.

RFC 9218 (Extensible Priorities for HTTP) deprecates the tree-based scheme and defines a simpler two-field signal:

Priority: u=0, i
  • u (urgency, 0–7): lower number = more urgent. u=0 for render-blocking HTML, u=1 for critical CSS, u=3 for stylesheets, u=5 for async scripts and fonts, u=7 for background prefetch.
  • i (incremental flag): when set, the server streams this response incrementally — sending a chunk, then switching to higher-urgency streams, then returning. Used for large bodies where partial data is useful.

The client sends a Priority: header (HTTP/2 and HTTP/3) or a PRIORITY_UPDATE frame (HTTP/3). The server honours these to schedule DATA frame transmission order across streams.

Browser support as of 2026: Chrome, Edge, Safari, and Firefox all ship Priority header support. Cloudflare, Fastly, and major CDNs have enabled it. Reported page-load improvements: up to 37% in some Cloudflare scenarios (by delivering render-blocking resources before images).

Why this works

Why the old priority tree failed. RFC 7540’s dependency tree let clients declare that stream #5 depends on stream #3 with a weight of 32. Servers were supposed to allocate bandwidth proportionally. In practice: browser implementations computed trees differently across versions; server implementations didn’t agree on weight semantics; and CDN edge nodes — which typically forward without re-interpreting priority — ignored it entirely. The result was a complex protocol feature that provided no consistent benefit. RFC 9218’s two-field model (urgency + incremental) is simple enough that every implementation agrees on its semantics.

MASQUE and QUIC Datagrams

MASQUE (Multiplexed Application Substrate over QUIC Encryption) is a family of IETF protocols that use HTTP/3 as a tunnelling layer:

  • CONNECT-UDP (RFC 9298): the client sends a CONNECT-UDP request to an HTTP/3 proxy; the request body becomes a tunnel for encapsulated UDP traffic.
  • CONNECT-IP: tunnels IP packets, enabling a full IP-over-QUIC VPN.

Apple’s iCloud Private Relay uses MASQUE: traffic flows through Apple Relay 1 (sees IP, not content) → Apple Relay 2 (sees content, not IP) → origin. This splits trust between two providers: neither alone can correlate IP and content.

QUIC DATAGRAM frames (RFC 9221) carry unreliable encrypted payloads inside a QUIC connection — sent once, not retransmitted if lost. This enables:

  • Real-time media with strict latency budgets (voice, video — where retransmission arrives too late to be useful).
  • Game state updates where a missed position update is harmless and a delayed one is wrong.

WebTransport (W3C + RFC 9298-related) exposes QUIC’s full capability to browser JavaScript: both reliable streams (like WebSocket) and unreliable datagrams (like UDP) from a browser page. Unlike WebSocket, WebTransport supports multiple concurrent streams per connection and does not require the upgrade dance. Chromium ships WebTransport; Firefox 124+ as well; Safari is behind a flag as of 2026.

WebTransport vs WebSocket vs SSE
WebTransport — reliable streams
Yes (multiple, multiplexed)
WebTransport — unreliable datagrams
Yes (QUIC DATAGRAM)
WebSocket — reliable
Yes (one bidirectional channel)
WebSocket — unreliable datagrams
No
SSE — reliable
Server-to-client only
WebTransport browser support (2026)
Chrome, Edge, Firefox 124+; Safari behind flag

Authentication schemes

Modern web apps use Authorization: Bearer <token> carrying a JWT or opaque session token. The HTTP layer transports the credential; OAuth 2.0 / OIDC defines how tokens are obtained.

  • Bearer tokens in headers — correct. Tokens in HTTP headers do not leak via Referer, browser history, or server access logs (which log the URL but typically redact headers).
  • Tokens in URLs — dangerous. ?token=abc appears in Referer headers sent to third-party resources, in browser history, in CDN and reverse-proxy access logs, and in analytics systems. Never put sensitive credentials in query strings.
  • Basic auth (Authorization: Basic base64(user:pass)) — survives for internal API tooling. Digest auth is effectively retired.
  • WWW-Authenticate — a 401 response includes this header to tell the client which scheme to use and with what parameters (realm for Basic, issuer for Bearer).

HTTP semantic correctness pitfalls

The HTTP machinery — browser retry logic, CDN caching, proxy rewriting — depends on correct status codes and headers. Common mistakes that cause production bugs:

Wrong status codes:

  • 200 OK for an error body {"error": "not found"} — CDNs cache the 200, proxy retry logic doesn’t trigger, browser console shows no error.
  • 200 OK with { "success": false } — breaks circuit breakers and health checks.
  • 301 Moved Permanently when the redirect is temporary — browsers cache 301 forever; changing it back requires clearing browser caches.

Vary header mistakes:

  • No Vary: Accept-Encoding on compressed responses — a cache may serve a Brotli-compressed body to a client that declared Accept-Encoding: gzip only, causing garbled content.
  • No Vary: Authorization on auth-differentiated cacheable responses — the CDN serves one user’s private data to another. Cache-Control: private prevents this at CDN level but Vary: Authorization is the correct signal.
  • Overly broad Vary: Cookie — causes a cache miss on every request since cookies differ per user; defeats caching entirely for authenticated users.

Cache-Control: private vs Vary: Authorization: use Cache-Control: private for user-specific data that must not be shared via CDN (and add no-store for sensitive data). Vary: Authorization tells shared caches to store separate variants per Authorization header value — correct for API responses that differ by token but are otherwise cacheable (e.g. by-user configuration data).

Auth endpoints returning 403 instead of 401: 401 Unauthorized means “authenticate first”; 403 Forbidden means “authenticated but not permitted”. Browsers and API clients handle these differently — 401 triggers credential prompts or refresh-token flows; 403 should not.

Trace it
1/4

A CDN is serving stale user-specific API data to the wrong users. Debug the caching configuration.

1
Step 1 of 4
Step 1: the API endpoint /api/user/profile returns 200 OK with user-specific JSON. Users are seeing each other's profiles. What CDN config allowed this?
2
Locked
Step 2: you add Cache-Control: private. Now CDN doesn't cache it. But an internal reverse proxy (Nginx) is still caching. What additional header is needed?
3
Locked
Step 3: Vary: Authorization is added. Now the proxy stores many variants. But anonymous users occasionally get cached authenticated responses. Why?
4
Locked
Step 4: the simplest fix for a highly sensitive endpoint (e.g. bank account summary)?
Pick the best fit

A real-time multiplayer game backend serves ~100k concurrent connections, mostly mobile clients on cellular. Pick the protocol stack.

Which RFC?

Which RFC deprecates HTTP/2's tree-based priority scheme and defines the simpler urgency-based Priority header?

Design challenge

Design the protocol layer for a global SaaS API serving 10k req/s from 50+ countries — mix of REST + WebSocket-style real-time, with mobile priority.

  • Average user RTT to your edge: 30–200 ms.
  • Lossy networks expected (mobile, satellite, hotel Wi-Fi).
  • Backwards compatibility with curl, fetch(), and gRPC-Web clients.
  • Auth via bearer tokens; sensitive endpoints must not be cached anywhere.
Recall before you leave
  1. 01
    Why did HTTP/2's priority dependency tree fail and what did RFC 9218 replace it with?
  2. 02
    What is the difference between WebTransport and WebSocket?
  3. 03
    List three semantic HTTP mistakes that cause CDN caching bugs in production.
Recap

RFC 9218 replaced HTTP/2’s complex priority dependency trees with a two-field signal: urgency (u=0–7, lower = more important) and incremental (i, stream partial data between higher-priority work). All major browsers and CDNs support it as of 2026. MASQUE (CONNECT-UDP, CONNECT-IP) tunnels arbitrary traffic through HTTP/3 — used in iCloud Private Relay. QUIC DATAGRAM frames (RFC 9221) carry unreliable encrypted payloads inside a QUIC connection; WebTransport exposes both reliable streams and unreliable datagrams to browser JavaScript. Authentication tokens belong in the Authorization header — never in URLs, which leak via Referer and access logs. Semantic correctness in status codes, Vary headers, and Cache-Control scope determines whether CDN and proxy caching behaves correctly; getting it wrong causes security leaks and stale-data bugs at scale.

Connected lessons
appears again in5
Continue the climb ↑HTTP versions: multiple-choice review
shortcuts expand
search
K
prev piece
k
next piece
j
cycle tier
t
this menu
?
sources5
expand
  1. 01
  2. 02
  3. 03
  4. 04
  5. 05

Trademarks belong to their respective owners. Editorial reference only.