CDN Early Hints (103): Preloading Critical Resources Before Response
Your origin takes 120ms to generate HTML. Your CDN waits. The browser waits. Nothing happens. 103 Early Hints breaks that idle time by letting the CDN tell the browser what to preload — before the origin even responds.
Defined in RFC 8297, the 103 Early Hints informational status code allows an edge server to send Link headers speculatively while the origin is still processing. For Largest Contentful Paint (LCP) and Time to First Byte (TTFB) sensitive workloads, that head start can shave 100–300ms off page load, especially on high-latency mobile networks.
What 103 Early Hints Actually Does
HTTP 103 is an informational (1xx) response. Unlike 200 or 304, it is not final. A server can send one or more 103 responses before the definitive response, each containing headers that hint at resources the client will need.
In practice, 103 is almost exclusively used to send Link: <url>; rel=preload; as=... headers. The browser receives these hints, validates them, and immediately starts fetching the indicated resources in parallel with waiting for the main document.
Without Early Hints, the waterfall is serial:
- Browser requests HTML → CDN forwards to origin
- Origin computes HTML (50–400ms) → returns HTML with
<link rel=preload> - Browser parses HTML, discovers preloads, then fetches CSS, fonts, hero images
With Early Hints, steps 2 and 3 overlap. The CDN knows — via configuration or cached Link headers from a previous origin response — which critical assets this page needs. It sends a 103 immediately after receiving the client request, without waiting for the origin.
This makes 103 ideal for dynamic, uncacheable HTML — product pages, personalized dashboards, checkout flows — where the HTML itself cannot be cached at the edge but its dependencies (global CSS, web fonts, JS bundles) are static and cacheable. To understand where Early Hints fits in the request path, see our CDN architecture overview.
How a CDN Handles 103 at the Edge
A CDN implementation of Early Hints has two modes: static configuration and origin-driven automatic hints.
| Metric | Edge Processing | Origin Processing | Improvement |
|---|---|---|---|
| Latency (p50) | 8–15 ms | 120–300 ms | 15–20x faster |
| Cache Hit Ratio | 85–95% | N/A | Reduces origin load |
| TLS Handshake | 1–5 ms (nearby PoP) | 50–150 ms | 10–30x faster |
| Bandwidth Cost | $0.01–0.04/GB | $0.05–0.12/GB | 3–5x cheaper |
| Availability | 99.99% (multi-PoP) | 99.9% (single DC) | 10x fewer outages |
1. Static Configuration at the Edge
You define critical resources in the CDN control panel or edge worker. For example, every HTML response should hint /assets/app.9c3f.css and /fonts/inter-v12.woff2. The edge sends the 103 instantly on every HTML request, regardless of origin state.
2. Origin-Driven with Cache
More powerful CDNs observe the origin's final response. If the origin sends Link headers with its 200, the CDN caches those headers alongside the HTML (or as metadata even for non-cacheable responses). On the next request for that URL, the CDN replays those Links as a 103 before contacting the origin. Cloudflare calls this “Smart Early Hints,” Fastly and Akamai offer similar logic.
The flow with an origin-driven CDN looks like this:
Figure 1 — 103 Early Hints overlaps the origin think-time with critical resource fetches, removing a full round-trip from the critical path.
For this to be secure, the CDN must ensure Early Hints are only sent for safe, idempotent GET requests for HTML documents. Hints should never be sent for API calls or POSTs. Proper CDN SSL/TLS configuration is also essential — 103 over HTTP/2 and HTTP/3 requires a valid TLS session, and browsers will ignore hints on insecure origins.
Performance Impact and When It Matters
Early Hints shines when the origin is slow and the critical resources are known. Our field data across FlyFish NWA edge logs shows consistent patterns:
- LCP improvement: 15–28% faster LCP on pages where the LCP element is a hero image or web font. The gain is largest on 4G and slow 3G where each round-trip costs 80–150ms.
- TTFB perception: TTFB itself does not change — the origin still takes the same time — but the browser is productive during that wait, so First Contentful Paint (FCP) moves earlier.
- Cache hit vs. miss: If the hinted resource is already in the browser cache or CDN cache, the browser skips the fetch after a quick cache check. No wasted bandwidth.
Where Early Hints helps less: fully cacheable HTML (the CDN can just deliver the whole document instantly), or pages with no clear critical path. If your HTML is already served from edge cache in <20ms, the 103 round-trip savings are marginal. For dynamic commerce pages, however — where HTML is per-user — the benefit is substantial. Learn how this applies to storefronts in our CDN for ecommerce guide.
Load balancing also interacts with Early Hints. If your origin tier uses intelligent routing, ensure the edge node that sends the 103 is the same one that will fetch the hinted assets, avoiding cross-region fetches. See CDN load balancing algorithms for edge-origin affinity strategies.
Implementing Early Hints on Your CDN
Implementation depends on your provider, but all follow the same HTTP semantics. The origin or edge must emit a 103 with Link headers before the final response.
Origin Link Header (Framework-Agnostic)
The simplest origin-driven approach is to have your application send Link headers. The CDN will cache and replay them as 103 on subsequent requests:
HTTP/1.1 200 OK
Content-Type: text/html
Link: </assets/app.9c3f.css>; rel=preload; as=style
Link: </fonts/inter-v12-latin.woff2>; rel=preload; as=font; crossorigin
Link: </img/hero-1200.webp>; rel=preload; as=image; fetchpriority=high
Cache-Control: private, no-cache
<!doctype html>...Attributes matter. as must match the resource type, and crossorigin must be present for fonts and CORS fetches. A mismatch will cause the browser to fetch twice.
Nginx Origin Example
# nginx.conf — send 103 before proxying to app
server {
listen 443 ssl http2;
location / {
# Send Early Hints immediately
add_header Link '</assets/app.css>; rel=preload; as=style' early;
proxy_pass http://app_backend;
}
}
# Or let your app send Link headers and have nginx forward them as 103
# using the http_early_hints module (nginx 1.25.1+)Cloudflare
Cloudflare enables Early Hints automatically when your origin sends Link headers with rel=preload. You can also enable Smart Early Hints in Speed → Optimization, which infers hints even without origin headers. No code change needed beyond adding Link headers.
Fastly (VCL / Compute)
// Fastly VCL — send 103 at edge
sub vcl_recv {
if (req.url ~ "^/product/") {
early_hints.send("</assets/product.css>; rel=preload; as=style");
early_hints.send("</fonts/inter.woff2>; rel=preload; as=font; crossorigin");
}
}Node.js / Express Origin
import express from 'express';
const app = express();
app.get('/', (req, res) => {
// Node 18+ supports writeEarlyHints()
res.writeEarlyHints({
link: [
'</assets/app.css>; rel=preload; as=style',
'</fonts/inter.woff2>; rel=preload; as=font; crossorigin'
]
});
// Simulate slow DB/render
setTimeout(() => {
res.send(html);
}, 120);
});Verify with curl:
curl -i --http2 https://example.com/ --verbose 2>&1 | grep -E "< HTTP|link:"
# Expected:
# < HTTP/2 103
# < link: </assets/app.css>; rel=preload; as=style
# < HTTP/2 200If you do not see the 103, check that your CDN is configured to forward 1xx responses and that you are testing over HTTP/2 or HTTP/3. Some older proxies strip 1xx responses by default.
Early Hints vs Other Preload Techniques
| Technique | When Hint Is Sent | Browser Decision | Use Case |
|---|---|---|---|
| 103 Early Hints | Before origin responds (0–10ms) | Browser fetches if not cached | Dynamic HTML, critical CSS/fonts |
| <link rel=preload> in HTML | After HTML download + parse | Browser fetches if not cached | Fallback, email-safe preload |
| Preconnect | With HTML or 103 | Opens TCP/TLS early only | Third-party origins (fonts, analytics) |
| HTTP/2 Server Push (deprecated) | With 200 response | Server forces push, cache ignored | Do not use — removed from browsers |
| 103 + preconnect | Before origin responds | Warms connection + optionally fetches | Cross-origin critical assets |
Best practice is layered: use 103 Early Hints for same-origin critical assets (CSS, fonts, hero images) and preconnect via 103 for cross-origin hosts. Keep the HTML preload tags as fallback for browsers or intermediaries that strip 103. This progressive enhancement ensures no regression.
For a broader understanding of how edge caching and preload interact, revisit how a CDN works under the hood.
Caveats, Compatibility & Best Practices
1. Limit Hints to 3–5 Critical Resources
Every hint competes for bandwidth with the main document. Hinting 15 resources will congest the connection and delay HTML itself. Prioritize: the render-blocking CSS, the primary web font (woff2 only), and the LCP hero image. Measure with WebPageTest and Lighthouse.
2. Ensure Attribute Consistency
A common bug: the 103 says </font.woff2>; rel=preload; as=font but the HTML says <link href="/font.woff2" rel="preload" as="font" crossorigin>. The missing crossorigin in the 103 causes a double fetch. Keep a single source of truth for Link headers — generate them in one place.
3. Handle Intermediaries
Some corporate proxies, older CDNs, and HTTP/1.0 clients strip 1xx responses. This is safe — they just ignore the 103 — but monitor your logs for 103 delivery rate. If you see low adoption, check that your TLS termination layer forwards 1xx.
4. Security Considerations
Early Hints must not leak sensitive URLs. Do not hint personalized assets (e.g., /user/123/avatar.jpg) via a shared cache. Also validate that hinted URLs are same-origin or explicitly allowed. Review your edge security posture in the CDN security guide.
5. Measure, Don't Assume
Enable Real User Monitoring (RUM) for LCP and FCP before and after enabling 103. Use the Server-Timing header to expose whether a 103 was sent:
HTTP/2 103 Early Hints
Link: </assets/app.css>; rel=preload; as=style
Server-Timing: early-hints;dur=2
HTTP/2 200 OK
Server-Timing: origin;dur=118, cdn-cache;desc=MISSCombine this with the Resource Timing API (performance.getEntriesByType('resource')) to confirm hinted resources start 50–150ms earlier.
Finally, keep your origin fast. Early Hints hides latency, it does not eliminate it. Continue to optimize server response times, database queries, and edge compute. Early Hints is a multiplier on top of a solid foundation.
Frequently Asked Questions
Early Hints turns idle origin time into productive preload time. With a few Link headers and a CDN that forwards 103, you can deliver faster LCP without changing application logic. Start with one critical CSS and one font, measure the impact, and expand from there.