HTTP 103 Early Hints: Faster Loads Before the Response

HTTP 103 Early Hints lets a server emit preload and preconnect Link headers before the final response, handing the browser a head start exactly as long as the origin's think-time. The payoff is bounded by that gap: if uncached HTML takes 400 ms to generate, 103 Early Hints can recover roughly 100–300 ms of it; if your TTFB is already 30 ms from an edge cache, it recovers close to nothing. Standardized as RFC 8297 in 2017, it is acted on by Chrome, Edge and Firefox as of 2026 and ignored by Safari. The engineering question is not "does it work" but "is my think-time window big enough to matter".

Diagram of HTTP 103 Early Hints sending preload headers before the final response between browser, CDN edge and origin

What HTTP 103 Early Hints actually does on the wire

103 is an informational status code. The server sends it as an interim response on the same request, with a header block containing Link values, then continues generating the real response and eventually sends the final 200 (or 302, or 500). The client is allowed to act on the hints immediately and must not treat them as the final answer.

A typical navigation exchange looks like this. Each Link value carries its URI-reference enclosed in angle brackets per RFC 8288; they are omitted below for readability.

:status: 103
link: /assets/app.8f2c.css; rel=preload; as=style
link: /assets/app.9d1a.js; rel=preload; as=script
link: https://media.example.com; rel=preconnect; crossorigin

:status: 200
content-type: text/html; charset=utf-8
link: /assets/app.8f2c.css; rel=preload; as=style
cache-control: private, no-store

Repeat the Link headers on the final response. Clients that ignored the 103 still get the preload, and any intermediary that stripped the interim response does not silently break your critical path.

Where the gain comes from: the think-time window

The only time early hints buys anything is the interval between the interim response and the first byte of the final response headers. Everything else — DNS, connection setup, TLS — has already happened, because the request is in flight. So the model is simple:

  • Window = finalResponseHeadersStart − firstInterimResponseStart (both exposed in Navigation Timing in Chromium since 2024).
  • Usable head start per resource = min(window, fetch duration of that resource).
  • LCP improvement = usable head start, but only for resources on the LCP critical path.

A render-blocking stylesheet that takes 120 ms to fetch, behind an origin with a 350 ms window, moves 120 ms earlier — the full fetch overlaps think-time. A 900 KB hero image with a 400 ms fetch, behind the same window, moves 350 ms earlier and no more. Vendor-published tests from 2022–2023 reported LCP gains in the 10–30% range on think-time-heavy pages; those results assume server-rendered, uncacheable HTML, which is precisely the workload where the window is wide.

The corollary matters more than the headline: pages served from an edge cache with a 5–20 ms TTFB have no window, so hints cost a header block and buy nothing.

Browser and CDN support for early hints http in 2026

Client / layerBehavior with a 103 responseConstraint
Chrome / Edge (Chromium)Acts on rel=preload and rel=preconnectTop-level navigations only; HTTP/2 or HTTP/3 only
Firefox (120+)Acts on hints for navigationsNarrower hint-type coverage than Chromium
Safari / WebKitIgnores the interim responseNo shipped support as of 2026
HTTP/1.1 hopsLegal per spec, unreliable in practiceOlder intermediaries mis-frame interim responses
Reverse proxies / edgePass through, synthesize, or dropBehavior is per-product and often per-config

The practical takeaway: assume roughly two-thirds of your navigation traffic can act on hints, and that any hop between origin and browser is free to discard them.

Which early hints CDN behavior does your provider implement?

Edge handling falls into three patterns. Pass-through forwards the origin's 103 unchanged. Synthesized means the edge remembers Link headers seen on earlier 200 responses for a URL and replays them as a 103 on subsequent requests — Cloudflare's early hints toggle works this way, which is why it needs a warm-up request per URL. Programmatic means you emit the interim response yourself from edge code, as Fastly allows from VCL and Compute.

Whichever provider sits in front of your origin — BlazingCDN, Cloudflare, Fastly or Amazon CloudFront — treat interim-response forwarding as a configuration question to settle before writing code, since it is rarely the default. BlazingCDN handles edge behavior per customer through custom enterprise CDN infrastructure, so raise it during onboarding rather than after launch.

Emitting hints without knowing the page yet

The hard part is ordering. You must send hints before you know what the page contains, because knowing requires rendering, and rendering is the thing you are trying to hide. Two workable sources: a build-time asset manifest keyed by route, or hints synthesized at the edge from prior responses.

server.on('request', function (req, res) {
  var hints = manifest.forRoute(req.url);   // built at deploy time
  if (hints.length) {
    res.writeEarlyHints({ link: hints });   // Node.js 18.11+
  }
  renderPage(req, function (html) {
    res.writeHead(200, { 'content-type': 'text/html; charset=utf-8' });
    res.end(html);
  });
});

Apache exposes H2EarlyHints for mod_http2, Go supports 1xx writes in net/http since 1.19, and mainline nginx still has no native directive as of 2026 — on nginx you emit from the application or the edge tier.

How to measure whether 103 Early Hints helped

Synthetic tests lie here, because they usually run against warm caches with a narrow window. Measure in RUM.

var nav = performance.getEntriesByType('navigation')[0];
var window_ms = nav.finalResponseHeadersStart - nav.firstInterimResponseStart;
var hinted = performance.getEntriesByType('resource').filter(function (e) {
  return e.initiatorType === 'early-hints';
});

When firstInterimResponseStart is 0, no interim response reached the browser — that alone tells you whether an intermediary is eating your 103. Ship the window value and the hinted-resource count as RUM dimensions, then compare p75 LCP between sessions with a non-zero window and sessions without, segmented by cache status on the HTML.

Verify this on your own stack

  • Check p75 of finalResponseHeadersStart minus firstInterimResponseStart on your uncached HTML routes. Under 100 ms, skip early hints entirely.
  • Check the cache status header on your HTML. If most navigations are edge hits, your addressable window is a small minority of traffic.
  • Count resources with initiatorType early-hints against the resources actually used by the page. A gap means wasted bytes.

Trade-offs and failure modes

Stale manifests are the expensive failure. Hash-named assets change on every deploy; a synthesized hint set that lags by one release preloads files that no longer exist, burning a round trip and a 404 on constrained mobile connections. Cross-origin rel=preconnect hints degrade gracefully by comparison, which makes them the safest first deployment.

Second, hints compete for bandwidth. Preloading three fonts and two scripts ahead of the HTML can push the LCP image behind them on the HTTP/2 priority tree. Hint the smallest set on the LCP path, not everything in the manifest.

Third, observability is one-sided. The server knows it sent a 103; it has no idea whether the client acted, whether a middlebox stripped it, or whether the preload was later discarded as unused. Chromium's Resource Timing attribution is your only reliable signal, and it does not cover Safari traffic at all — so in-body preload tags stay, permanently.

Finally: 103 responses are never cached and never carry a body. If a component in your chain tries to cache or buffer them, you will see the window collapse to zero rather than an explicit error.

FAQ: 103 Early Hints in practice

What is HTTP 103 Early Hints?

HTTP 103 Early Hints is an informational status code defined in RFC 8297 that lets a server send Link headers, typically rel=preload and rel=preconnect, before the final response is ready. The client starts fetching those resources during server think-time. The interim response carries no body and does not replace the final status.

Does 103 Early Hints work over HTTP/1.1?

The specification permits it, but browsers do not rely on it. Chromium processes early hints only on HTTP/2 and HTTP/3 navigations, and older HTTP/1.1 intermediaries can mishandle interim responses on the wire. In production, treat HTTP/2 or HTTP/3 end-to-end as a prerequisite for HTTP 103.

Does an early hints CDN configuration help cache hits?

Almost never. On an edge cache hit the final response headers arrive within roughly 5–20 ms, leaving no think-time window for the browser to fill. Early hints pays off on uncacheable, personalized or authenticated HTML where the origin needs 200 ms or more to generate the response.

Can early hints make a page slower?

Yes, in two ways. Hinting resources the page does not use wastes bandwidth on constrained connections, and hinting too many resources can delay the LCP element by competing for the same connection. Keep the hint set to the two or three assets on the critical rendering path.

Instrument the window before you build anything

Spend one week on measurement, not implementation. Add finalResponseHeadersStart, firstInterimResponseStart and HTML cache status to your RUM beacon, then bucket p75 LCP by window size. If your p75 window on uncached routes is under 100 ms, the honest answer is that 103 Early Hints is not your bottleneck and origin render time is. If it clears 200 ms, start with cross-origin rel=preconnect hints only — they cannot 404, they survive stale manifests, and they will tell you within days whether the interim response is even reaching your users.