HTTP/2 Server Push Reference

HTTP/2 PUSH_PROMISE frame mechanics with deprecation notes and 103 Early Hints

Reference for HTTP/2 Server Push: the PUSH_PROMISE frame, RST_STREAM cancellation, the SETTINGS_ENABLE_PUSH flag, why browsers removed it, and 103 Early Hints with rel=preload as the modern replacement. It runs free in your browser on Gera Tools, with nothing uploaded.

Last updated Source: Gera Tools

Is HTTP/2 Server Push still usable?

No, not in practice. Chrome removed support in version 106 (2022) and other engines followed, citing poor real-world performance and frequent over-pushing of already-cached resources. HTTP/3 never specified push at all. Treat it as deprecated and use 103 Early Hints instead.

HTTP/2 Server Push let a server send resources to a client before they were requested, using a PUSH_PROMISE frame. In practice it under-delivered and is now removed from browsers. This reference documents how it worked, why it failed, and what to use instead.

How it worked

A pushed resource follows this lifecycle on an HTTP/2 connection:

  1. The server sends a PUSH_PROMISE frame on the client’s request stream, reserving a new server-initiated (even-numbered) stream ID and carrying the promised request header block.
  2. The server then sends HEADERS + DATA for that pushed response on the reserved stream.
  3. The client may accept it, or send RST_STREAM with CANCEL / REFUSED_STREAM to decline — useful when the resource is already in cache.
  4. A client can disable push for the whole connection with SETTINGS_ENABLE_PUSH = 0.

The intent was to eliminate the “discovery” round-trip: instead of waiting for the browser to parse HTML and then request CSS and JS, the server could start sending those files immediately. In theory this saved one full round-trip of latency for critical resources.

Why it failed

The fatal flaw was that servers had no way to know what the browser already had in its cache. A returning visitor who already had app.css cached would receive a redundant push of the same file, wasting bandwidth and CPU. Servers tended to over-push — sending everything on the page regardless of what the client needed — and the interaction with HTTP/2 stream priority was poorly specified and implemented inconsistently.

Chrome removed server push support in version 106 (September 2022), and HTTP/3 (RFC 9114) never specified push at all. The feature is now effectively deprecated across the web.

The modern replacement — 103 Early Hints

Instead of pushing bytes, the server sends an informational 103 Early Hints response carrying Link headers with rel=preload while it prepares the real response:

HTTP/2 103 Early Hints
Link: </app.css>; rel=preload; as=style
Link: </app.js>; rel=preload; as=script

HTTP/2 200 OK
Content-Type: text/html
...

The browser starts fetching the hinted resources immediately but stays in control of caching. If a file is already cached, it simply ignores the hint — no wasted bandwidth. The server can send 103 as soon as it starts processing the request, before it finishes generating the HTML, so the critical sub-resource fetches begin at the same time the server is working.

103 Early Hints vs Server Push

Server Push (deprecated)103 Early Hints
Browser cache awarenessNone — always sends bytesClient checks cache before fetching
Client controlRST_STREAM to cancelNormal cache logic
HTTP/3 supportNoYes
Implementation complexityHigh (server manages streams)Low (add a response header)
Browser supportRemovedChrome, Edge, Firefox, Cloudflare

This is the recommended path on HTTP/2 and HTTP/3. Most CDNs and frameworks support 103 Early Hints via response headers rather than requiring HTTP/2-level plumbing.