Optimizing Interaction to Next Paint (INP) with CDN Edge Strategies
Interaction to Next Paint replaced First Input Delay as a Core Web Vital in March 2024, fundamentally changing how we measure page responsiveness. FID only captured the delay before the first interaction was processed. INP measures every interaction throughout the page lifecycle and reports the worst one. This shift exposed responsiveness problems that FID masked, and it created new optimization opportunities at the CDN layer. While INP is ultimately a browser-side metric, the CDN controls what code reaches the browser, how fast it arrives, and whether the browser’s main thread is free to respond to user interactions. For a broader view of CDN impact on all Core Web Vitals, see CDN and Core Web Vitals: LCP, FID, and CLS.
Understanding What INP Actually Measures
INP captures the full interaction lifecycle: the time from user input (click, tap, keypress) through JavaScript event handler execution, DOM updates, style recalculation, layout computation, and painting the updated pixels to the screen. A good INP is under 200 milliseconds. Needs improvement is 200 to 500 milliseconds. Poor is above 500 milliseconds.
The input delay phase is where CDN optimizations have the most impact. Input delay occurs when the browser’s main thread is busy executing other JavaScript when the user interacts. If the main thread is parsing a 500-kilobyte JavaScript bundle when the user clicks a button, the click event queues until parsing completes. CDN-level optimizations that reduce JavaScript bundle size, split code more effectively, and deliver scripts with optimal timing directly shrink this input delay.
JavaScript Delivery Optimization for INP
The primary CDN-level lever for INP is controlling how JavaScript reaches the browser. Three delivery optimizations directly reduce main thread contention and improve interaction responsiveness.
| 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 |
Script Prioritization with Early Hints
HTTP 103 Early Hints allow the CDN to tell the browser about critical resources before the HTML response is ready. For INP optimization, the most valuable resources to hint are the JavaScript files that contain interaction event handlers. When the browser receives an Early Hint for an interaction script, it begins downloading and parsing that script while still waiting for the HTML. By the time the page renders and the user can interact, the event handlers are already registered and ready to execute.
# CDN configuration — Early Hints for interaction-critical scripts
# These headers are sent as 103 Early Hints before the 200 response
# Critical: interaction handlers must be ready before first interaction
Link: </assets/interactions.js>; rel=preload; as=script; fetchpriority=high
# Important: framework runtime needed for event processing
Link: </assets/framework.js>; rel=preload; as=script; fetchpriority=high
# Less critical: analytics and monitoring can load later
Link: </assets/analytics.js>; rel=prefetch; as=script
# CDN cache rule — different priority for different script categories
location ~* /assets/interactions\..*\.js$ {
add_header Cache-Control "public, max-age=31536000, immutable";
add_header X-Script-Priority "critical";
}
location ~* /assets/(analytics|tracking)\..*\.js$ {
add_header Cache-Control "public, max-age=86400";
add_header X-Script-Priority "deferred";
}
The CDN can determine which scripts to hint based on the page type. A product page needs the add-to-cart handler immediately but does not need the checkout validation script. A search results page needs the filter interaction script but not the review submission handler. Edge logic that maps page types to critical scripts enables per-page Early Hints without requiring the origin to maintain this mapping. More details on Early Hints implementation are covered in CDN Performance Optimization.
Edge-Side Code Splitting
Traditional code splitting happens at build time: bundlers analyze import dependencies and create chunks that load on demand. Edge-side code splitting adds a runtime layer where the CDN modifies the HTML response to reference only the JavaScript chunks needed for the current page.
The implementation works by maintaining a manifest that maps page routes to their required JavaScript chunks. When a request arrives at the edge, the edge function identifies the page type from the URL pattern, looks up the required chunks in the manifest, and rewrites the HTML to include only those script tags. Scripts for other pages are removed from the initial load and loaded on demand when the user navigates.
// Edge function — page-specific script injection
const PAGE_SCRIPTS = {
'/products/*': ['framework.js', 'product-interactions.js', 'cart.js'],
'/search': ['framework.js', 'search-filter.js', 'pagination.js'],
'/checkout': ['framework.js', 'checkout-validation.js', 'payment.js'],
'/blog/*': ['framework.js', 'comments.js'],
'*': ['framework.js'],
};
export default {
async fetch(request) {
const url = new URL(request.url);
const response = await fetch(request);
// Only transform HTML responses
if (!response.headers.get('Content-Type')?.includes('text/html')) {
return response;
}
// Find matching page pattern
const scripts = findMatchingScripts(url.pathname, PAGE_SCRIPTS);
// Rewrite HTML to include only needed scripts
return new HTMLRewriter()
.on('script[data-split]', {
element(el) {
const src = el.getAttribute('src');
const filename = src.split('/').pop();
if (!scripts.includes(filename)) {
el.remove();
}
},
})
.transform(response);
},
};
The INP improvement from edge-side code splitting comes from reducing the total JavaScript the browser must parse. A monolithic 800-kilobyte bundle takes 200 to 400 milliseconds to parse on a mid-range mobile device. If code splitting reduces the initial load to 200 kilobytes for a specific page, parsing time drops to 50 to 100 milliseconds. That freed main thread time directly reduces input delay for the first interaction.
Compression and Protocol Optimization
The time JavaScript spends downloading directly affects how quickly the browser can parse it and free the main thread. CDN-level Brotli compression reduces JavaScript file sizes by 15 to 25 percent more than gzip, and HTTP/3 with QUIC eliminates head-of-line blocking that delays individual script downloads when one packet is lost.
The combination of Brotli compression, HTTP/3 delivery, and Early Hints creates a compounding effect. A 300-kilobyte JavaScript file compressed with Brotli to 75 kilobytes, delivered over HTTP/3 without head-of-line blocking, and prefetched via Early Hints reaches the browser’s parser faster than the same file with gzip over HTTP/1.1 fetched only after HTML parsing completes. The cumulative time savings of 100 to 200 milliseconds directly translates to improved input delay for the first interaction.
Edge-Side API Acceleration for Processing Time
The processing phase of INP includes any network requests that the interaction handler initiates and waits for. When a user clicks “Add to Cart” and the handler sends an API request to update the cart, the time waiting for the API response is part of INP if the handler delays the UI update until the response arrives.
Moving API endpoints to the CDN edge reduces this network round-trip from 100 to 300 milliseconds (centralized origin) to 5 to 20 milliseconds (edge function). For interactions that depend on API responses to update the UI, this reduction directly improves INP.
// Edge function — low-latency cart API at the edge
export default {
async fetch(request, env) {
const url = new URL(request.url);
if (url.pathname === '/api/cart/add' && request.method === 'POST') {
const body = await request.json();
const sessionId = getSessionId(request);
// Read current cart from edge storage (Durable Object or KV)
const cart = await env.CARTS.get(sessionId) || { items: [] };
// Add item — runs at the edge, no origin round-trip
cart.items.push({
productId: body.productId,
quantity: body.quantity,
addedAt: Date.now(),
});
// Write updated cart to edge storage
await env.CARTS.put(sessionId, JSON.stringify(cart));
// Sync to origin asynchronously — does not block response
ctx.waitUntil(syncToOrigin(env.ORIGIN, sessionId, cart));
// Response returns in 5-20ms from the edge
return new Response(JSON.stringify({
success: true,
cartCount: cart.items.length,
}), {
headers: { 'Content-Type': 'application/json' },
});
}
return fetch(request);
},
};
The edge API pattern is most effective for read-heavy interactions (search filtering, pagination, autocomplete) and simple write operations (cart updates, bookmark toggles, vote submissions) that can be processed at the edge and synchronized to the origin asynchronously. Complex transactions that require database consistency still need to route to the origin, but the majority of user interactions on typical web applications fall into the edge-processable category.
Reducing Presentation Delay with CDN-Delivered Styles
The presentation phase of INP includes style recalculation, layout, and paint. While these browser operations happen outside the CDN’s direct control, the CDN influences them through how efficiently CSS reaches the browser and how much DOM the interaction modifies.
Critical CSS inlining at the CDN edge ensures that the styles needed for interaction feedback (button hover states, loading spinners, dropdown animations) are available in the initial HTML. Without these styles, the browser must download an external stylesheet before it can paint the visual feedback for an interaction, adding to presentation delay.
// Edge function — inline critical interaction CSS
const CRITICAL_INTERACTION_CSS = `
.btn:active { transform: scale(0.98); }
.btn[aria-busy="true"] {
opacity: 0.7;
pointer-events: none;
}
.dropdown[open] { display: block; }
.toast { animation: slideIn 0.2s ease-out; }
@keyframes slideIn {
from { transform: translateY(100%); opacity: 0; }
to { transform: translateY(0); opacity: 1; }
}
`;
export default {
async fetch(request) {
const response = await fetch(request);
if (!response.headers.get('Content-Type')?.includes('text/html')) {
return response;
}
return new HTMLRewriter()
.on('head', {
element(el) {
el.append(
``,
{ html: true }
);
},
})
.transform(response);
},
};
Font loading strategy also affects presentation delay. When an interaction changes text content and the required font is not yet loaded, the browser may render the new text in a fallback font and then repaint when the web font arrives, extending the time to final paint. The CDN can preload fonts using Early Hints and set font-display: optional to prevent late font swaps that extend presentation delay during interactions.
Measuring INP Impact of CDN Changes
INP optimization requires measuring real-user interactions, not synthetic tests. Lab tools like Lighthouse measure Total Blocking Time (TBT) as an INP proxy, but TBT only captures main thread blocking during load, not interaction responsiveness. True INP measurement comes from field data: the Chrome User Experience Report (CrUX) and Real User Monitoring (RUM) instrumentation.
After implementing CDN-level INP optimizations, track three metrics: CrUX INP at the 75th percentile (the value Google uses for Core Web Vitals assessment), RUM INP distribution by page type (identify which pages benefit most from each optimization), and interaction breakdown by phase (input delay, processing, presentation) to identify the next optimization target. For detailed monitoring implementation, see Real User Monitoring (RUM) for CDN.
| CDN Optimization | INP Phase Targeted | Typical Improvement | Effort Level |
|---|---|---|---|
| 103 Early Hints for interaction JS | Input delay | 30–80ms | Low |
| Edge-side code splitting | Input delay | 50–150ms | Medium |
| Brotli compression | Input delay | 20–50ms | Low |
| HTTP/3 + QUIC | Input delay | 10–40ms | Low |
| Edge API endpoints | Processing time | 80–280ms | High |
| Critical CSS inlining | Presentation delay | 10–30ms | Low |
| Font preloading via Early Hints | Presentation delay | 5–20ms | Low |
The cumulative effect of layering these optimizations produces dramatic INP improvements. A site with a 75th percentile INP of 450 milliseconds (poor) that implements all seven optimizations can reasonably expect to reach 150 to 200 milliseconds (good). The highest-impact individual optimization is typically edge API endpoints for interaction-heavy pages and code splitting for content-heavy pages. Start with the optimizations that target the dominant INP phase for your specific page types, then layer additional optimizations to push scores below the 200-millisecond threshold.
The CDN’s role in INP optimization will grow as edge platforms gain more capabilities for controlling JavaScript execution, HTML transformation, and API acceleration. Teams that establish CDN-level INP monitoring now will be well-positioned to adopt new edge optimizations as they become available, maintaining competitive responsiveness scores as Google’s thresholds tighten and user expectations increase. For the SEO implications of these improvements, see CDN and SEO: How Edge Performance Impacts Search Rankings.