HTTP/3 Extensible Priorities: A Simpler Way to Schedule Web Traffic

Cloudflare has announced full support for HTTP/3 Extensible Priorities, implementing the RFC 9218 standard across all plans. The goal is straightforward: when a web page consists of dozens of assets competing for limited bandwidth, the server needs to send the right bytes at the right time. Prioritization is the mechanism that decides which objects get dedicated bandwidth and which share it. When that decision is wrong, other performance optimizations can be undermined.

The new scheme is available to all Cloudflare customers. Paid users get access to an enhanced version with additional performance tuning options. In Cloudflare's testing, the feature improved Largest Contentful Paint (LCP) by up to 37% on blog.cloudflare.com, dropping it from 2.06 seconds to 1.29 seconds.

Why a Real Page Loads Faster

To understand the gains, consider a typical page load. Without smart prioritization, a waterfall diagram of blog.cloudflare.com reveals the problem. The LCP image, 1937-1.png at 30.4 KB, is requested with priority u=3,i, placing it in the same round-robin bandwidth-sharing bucket as other images. Meanwhile, a defer JavaScript file (index.js, 217 KB) is assigned priority u=3,i=?0, putting it ahead of the image group server-side.

That ordering hurts performance twice. First, the large script is transmitted before the LCP image finishes loading. Second, once index.js arrives, the browser must parse and execute it, saturating the CPU for roughly 300 ms and delaying the LCP paint even after the image has been delivered.

With a server-side override promoting the LCP image from u=3,i to u=2,i, the image leapfrogs the JavaScript. Transmission of index.js halts around the 1.2-second mark while the image is delivered in full. Because the remaining script arrives a couple hundred milliseconds later, there is no CPU contention at paint time, and LCP improves dramatically.

Two Parameters Replace a Dependency Tree

HTTP/2 priorities relied on a dependency tree model with 255 weights and complex mutual or exclusive dependencies. That approach proved difficult to implement and port to HTTP/3. Extensible Priorities collapses the model to two parameters.

  • Urgency — an integer from 0 to 7, with 0 being most important. The default is 3.
  • Incremental — a boolean, defaulting to false. A value of true means the client can process the object as parts arrive; false means the entire object must be received before processing begins.

Typical assignments for common resource types:

  • HTML documents: urgency 0, incremental true (streamable, highest importance)
  • CSS: urgency 1, incremental false (blocks rendering, but must be whole)
  • Off-screen images: urgency 3, incremental true (streamable, low importance)
  • Hero or LCP images: urgency 1 or 2, incremental value depends on the use case

Clients send these priority signals either in an HTTP header field on the request stream, or via an HTTP/3 PRIORITY_UPDATE frame on the control stream when priorities change mid-flight. Both use the Structured Fields Dictionary format (RFC 8941), with parameters shortened on the wire: u for urgency and i for incremental.

Defaults can be omitted, leading to compact expressions. A request for an important CSS file might send just u=1 (urgency 1, incremental false). A low-priority image could send i=?1 (urgency 3, incremental true). Boolean true can also be shortened further, to just i.

Scheduling Rules and Server Overrides

RFC 9218 provides scheduling recommendations rather than a single mandated algorithm. The guidance boils down to a few rules. Request order matters most: clients issue requests when they want the objects, and servers should serve in that order, using stream IDs to reconstruct ordering in HTTP/3's unordered stream environment. Urgency ordering is next. Non-incremental requests should be served serially and in full, while incremental requests can be served in parallel, round-robin style, sharing bandwidth.

In practice, the scheduler serves non-incremental requests alone per urgency level, then spreads incremental requests across available bandwidth. This gives dedicated capacity to critical blocking resources while allowing progressive ones to trickle in without starving anything else.

Servers need not stop at honoring client signals. Extensible Priorities allows a response header to override the client's request priority. That capability is especially useful in proxying architectures where Cloudflare terminates HTTP/3 in front of a backend like Workers. The proxy can pass request headers through, let the backend inspect them, and return different priority response headers if needed.

Consider a page with several <img> tags near the top of the HTML. The browser may issue requests before it knows whether each image will land in the viewport. If it guesses wrong, an LCP image could end up in the low-priority shared image bucket. A developer who knows the intended layout can override the priority at response time, skipping the lag-prone PRIORITY_UPDATE frame that may arrive too late to matter.

These server-side overrides complement existing techniques like async, defer, preload links, and the newer fetchpriority attribute. fetchpriority nudges the browser to send requests earlier or later, and can influence urgency selection, but it does not set explicit priority values. Response headers provide a direct, unambiguous mechanism when the plain numbers are what matters.

Availability and Rollout

HTTP/3 Extensible Priorities is rolling out over the next few weeks as part of the HTTP Priorities feature already available for HTTP/2. No configuration is needed from site owners: browsers send Extensible Priorities signals with HTTP/3 requests automatically, and Cloudflare's scheduler handles the rest.