HTTP/2 Prioritization and Server Push in Chromium
This article provides a technical overview of how the Chromium web browser manages HTTP/2 traffic. Specifically, it explains how Chromium utilizes a linear dependency tree and modern extensible priorities to handle HTTP/2 stream prioritization, as well as why the browser engine permanently deprecated and removed support for HTTP/2 Server Push in favor of better alternatives like 103 Early Hints.
How Chromium Handles HTTP/2 Stream Prioritization
HTTP/2 allows multiple requests and responses to be multiplexed over a single TCP connection. To prevent low-priority assets (like footer images) from blocking critical assets (like render-blocking CSS), HTTP/2 introduced stream prioritization.
While the original HTTP/2 specification (RFC 7540) allows browsers to build complex branching trees of stream dependencies and weights, Chromium takes a much stricter, simplified approach.
The Linear Dependency Tree
Instead of creating a wide, branching tree, Chromium constructs a strictly linear list—essentially a linked list of requests—to dictate the exact order in which the server should send data.
- Internal Priority Buckets: Chromium assigns every
resource one of five internal priority levels:
Highest(HTML, CSS, Fonts),Medium(JavaScript, XHR),Low(Images),Lowest, orIdle. - Exclusive Dependencies: When Chromium requests a new resource, it places the stream into this linear chain based on its bucket. It uses the HTTP/2 "exclusive" flag to insert higher-priority streams directly ahead of lower-priority ones.
- FIFO Execution: Streams of the same priority level are stacked sequentially on a First-In, First-Out (FIFO) basis. This forces the server (if it respects Chromium's prioritization signals) to dedicate all bandwidth to the top item in the chain before moving to the next.
Transition to Extensible Priorities (RFC 9218)
The original HTTP/2 prioritization scheme proved too complex for many servers to implement correctly, leading to degraded web performance when servers mismanaged Chromium's linear tree.
To solve this, Chromium adopted the newer Extensible Prioritization
Scheme (RFC 9218), originally designed for HTTP/3, and applied it to
HTTP/2. When communicating with modern servers that support it, Chromium
abandons the complex dependency tree and instead sends a standard
Priority HTTP header containing two simple parameters:
- Urgency (u): An integer from 0 to 7 indicating importance (0 being the highest priority, like the main HTML document).
- Incremental (i): A boolean flag indicating whether the resource can be processed progressively as bytes arrive (like an image) or if it needs to be downloaded completely before use (like a script).
The Deprecation of HTTP/2 Server Push
HTTP/2 Server Push was designed to improve page load times by allowing a server to preemptively send resources (such as a CSS or JavaScript file) to the browser before the browser even parsed the HTML and requested them. However, starting in Chrome 106, Chromium completely disabled HTTP/2 Server Push by default.
Chromium deprecated and removed this feature for three primary reasons:
1. Wasted Bandwidth and Cache Contention
The biggest flaw with Server Push was that the server had no reliable
way of knowing what was already in the browser's cache. Servers
frequently pushed heavy assets that the user's browser had already
downloaded during a previous visit. While Chromium could cancel the
redundant push by sending a RST_STREAM frame, the network
latency meant that much of the wasted data was already in flight,
consuming bandwidth that should have been used for critical, uncached
resources.
2. Poor Real-World Performance and Low Adoption
Because pushed streams often competed for bandwidth with the main HTML document, improper Server Push configurations frequently made websites load slower rather than faster. Furthermore, Chromium's telemetry data revealed that over 99% of HTTP/2 connections never used Server Push, and of the connections that did, the vast majority of pushed resources went completely unused by the browser.
3. Architectural Complexity
Supporting Server Push required Chromium to maintain a separate "push cache" in its networking stack. This added significant code complexity, maintenance overhead, and recurring security vulnerabilities for a feature that rarely provided a net positive to the end user.
How Chromium Replaces Server Push
Instead of HTTP/2 Server Push, Chromium relies on safer, more predictable mechanisms to load resources early:
- 103 Early Hints: This is the direct replacement for
Server Push. When a server needs time to generate the main HTML page
(e.g., waiting on a database query), it immediately sends an
HTTP 103 Early Hintsstatus code containingLinkheaders for critical CSS and JS files. Chromium receives these hints, checks its local cache, and initiates standard requests only for the files it does not already have. - Preload Directives: For fast-responding servers,
standard
<link rel="preload">tags placed in the HTML head or HTTP response headers allow Chromium's preload scanner to fetch critical sub-resources immediately without the risk of cache over-pushing.