Five years ago, we built a company around HTTP/2 server push. Here is what we learned:<p>- The interaction of HTTP/2 push with browser caches were left unspecified for the most part, and browsers implemented different ad-hoc policies.<p>- Safari in particular was pretty bad.<p>- Since HTTP/2 Push worked at a different layer than the rest of a web application, our offering centered around reverse-engineering traffic patterns, with the help of statistics and machine learning. We would find the resources which were more often not cached, and push those.<p>- HTTP/2 Push, when well implemented, offered reductions in time to DOMContentLoaded in the order of 5 to 30%. However, web traffic is noisy and visitors fall in many different buckets by network connection type and latency. Finding that 5% to 30% performance gain required looking to those buckets. And, DOMContentLoaded doesn't include image
loading, and those dominated the overall page loading time.<p>- As the size of, say, Javascript increases, the gains from using HTTP/2 Push asymptotically tend to zero.<p>- The PUSH_PROMISE packets did indeed could increase loading time because they needed to be sent when the TCP connection was still cold. At that point in time, each byte costs more latency-wise.<p>- If a pushed resource was not matched or not needed, the loaded time increased again.<p>Being a tiny company, we eventually moved on and found other ways of decreasing loading times that were easier for us to implement and maintain and also easier to explain to our customers.
I think this is the right decision. I looked at HTTP/2 push in 2017 and the design is very confusing, and the implementations are pretty bad. <a href="https://jakearchibald.com/2017/h2-push-tougher-than-i-thought/" rel="nofollow">https://jakearchibald.com/2017/h2-push-tougher-than-i-though...</a>.<p>Chrome's implementation was best, but the design of HTTP/2 push makes it really hard to do the right thing. Not just when it comes to pushing resources unnecessarily, but also delaying the delivery of higher priority resources.<p><link rel="preload"> is much simpler to understand and use, and can be optimised by the browser.<p>Disclaimer: I work on the Chrome team, but I'm not on the networking team, and wasn't involved in this decision.
This is pretty funny. After all the fuss, turns out that server push isn't really useful. I'm half impressed that they are able to actually admit they were wrong (implicitly of course) by removing it. I can't say I'm surprised, either. I could never think of a reasonable use case for it.<p>With the variety of streaming options available now, it really seems antiquated.
Server push never made any sense anyway for most subresources. The server doesn't know about the state of the browser's cache, so using server push for a subresource could cause it to needlessly push a subresource that was already cached by the browser.<p>Maybe it is useful outside of the browser context, e.g. in gRPC.
HTTP/2 server push is odd. When you can get the most benefit out of it, you usually don't care, because your resources are small and load quickly anyway. And when you care (because your resources are big don't load quickly enough), HTTP push actually hurts you, because you are pushing the same big resource on every page load.<p>I have tried to use it once, and the hassle of distinguishing between first time visits and repeated visits is simply not worth it. Even the hassle of using <link rel="preload"> is usually not worth it in large apps — if you have time for that, it can be better spent on reducing size of assets.
HTTP/2 Push allows to _really_ optimize first page load, giving a wow effect. (Especially when you can use a single server w/o geodns to serve the whole world with a really low latency!)<p>I use it on my pet project website, and it allows for a remarkable first page load time.<p>And I don't have to make all these old-school tricks, like inlining CSS & JS.<p>HTTP/2 Push allows for such a pleasant website development. You can have hundreds of images on the page, and normally, you'd be latency-bound to load it in a reasonable amount of time. And the way to solve it old-school is to merge them all into a one big image, and use CSS to use parts of the image instead of separate image URLs. This is an ugly solution for a latency problem. Push is so much better!<p>The fact that 99% of people are too lazy to learn a new trick shouldn't really hamstring people into using 30-year old tricks to get to a decent latency!
They quote a study by Akamai, a CDN company. Of course, if you run a CDN then you don't like products that help reduce latency when you don't have a CDN...<p>Server push is most useful in cases where latency is high, i.e. server and client are at different ends of the globe. It helps reduce round trips needed to load a website. Any good CDN has nodes at most important locations so the latency to the server will be low. Thus server push won't be as helpful.
Why doesn't the client keep a bloom filter of already-requested URLs on that website and send it along to the server on the first request? That way, you'd get the less-space benefit of link rel, but the latency benefit of push.<p>Also, this is very Google: "Well, few people have adopted it over five years, time to remove it." HTTPS is almost as old as HTTP and is only now starting to become universal. Google has no patience, seriously.
Server Push has a use case for web APIs. I just published a benchmark showing that under certain conditions APIs using Server Push (such as APIs implementing the <a href="https://vulcain.rocks" rel="nofollow">https://vulcain.rocks</a> specification) can be 4x times faster than APIs generating compound documents (GraphQL-like): <a href="https://github.com/dunglas/api-parallelism-benchmark" rel="nofollow">https://github.com/dunglas/api-parallelism-benchmark</a><p>They key point for performance is to send relations in parallel in separate HTTP streams.
Even without Server Push Vulcain-like APIs are still faster than APIs relying on compound documents thanks to Preload links and to HTTP/2 / HTTP/3 multiplexing.<p>Using Preload links also fixes the over-pushing problem (pushing a relation already in a server-side or client-side cache), some limitations regarding authorization (by default most servers don't propagate the Authorization HTTP header nor cookies in the push request), and and is easier to implement.<p>(By the way Preload links were supported from day 1 by the Vulcain Gateway Server.)<p>However, using Preload links introduce a bit more latency than using Server Push. Does the theoretical performance gain is worth the added complexity? To be honest I don't know. I guess it doesn't.<p>Using Preload links combined with Early Hints (the 103 status code - RFC 8297) may totally remove the need for Server Push. And Early Hints are way easier than Server Push to implement (it's even possible in PHP!).<p>Unfortunately browsers don't support Early Hints yet.<p>- Chrome bug: <a href="https://bugs.chromium.org/p/chromium/issues/detail?id=671310" rel="nofollow">https://bugs.chromium.org/p/chromium/issues/detail?id=671310</a><p>- Firefox bug: <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=1407355" rel="nofollow">https://bugzilla.mozilla.org/show_bug.cgi?id=1407355</a><p>For the API use case, it would be nice that Blink adds support of Early Hints before killing Server Push!
I'm surprised about the timing.<p>The serverless/edge technologies becoming available at CDNs are making it easy to imagine "automatic push" could come soon.<p>Any chance there are folks from Vercel or Netlify here and can shed light on why push hasn't been implemented in their platforms (or if it has)? At first glance, it seems like Next.js in particular (server rendering) is ripe for automatic push.
To me, the jury is very much still out on push. It's entirely in-determinate how useful it is, because only a handful of people have stepped up to try. There is a lot of trickery to getting the server to determine what resources to push, that it knows the client needs, but basics like "let's look at the main pages etag to figure it out" got very little experimentation & tries, certainly very few documented.<p>> Chrome currently supports handling push streams over HTTP/2 and gQUIC, and this intent is about removing support over both protocols. Chrome does not support push over HTTP/3 and adding support is not on the roadmap.<p>I am shocked & terrified that google would consider not supporting a sizable chunk of HTTP in their user-agent. I understand that uptake has been slow. That this is not popular. But I do not see support as optional. This practice, of picking & choosing what to implement of our core standards, of deciding to drop core features that were by concensus agreed upon- because 5 years have passed & we're not sure yet how to use it well yet- is something I bow my head to & just hope, hope we can keep on through.
Well that sucks. Caddy has supported HTTP/2 push for a very long time (except for a few months after v2 was released since it was a total rewrite). <a href="https://caddyserver.com/docs/caddyfile/directives/push" rel="nofollow">https://caddyserver.com/docs/caddyfile/directives/push</a>
Do web-transport obscolete push?
<a href="https://w3c.github.io/webtransport/" rel="nofollow">https://w3c.github.io/webtransport/</a><p>I had read a technical comment once that told that HTTP 2 push was superior to websocket but couldn't remember why.
Also what's the difference between push and server sent events?
What if on link hover, some javascript code notifies the server and the server pushes the page? When the user clicks the link the page will have already been downloaded. Would that not be possible and useful?
So instead of pursuing the idea of server pushing your CSS so the top of your page renders fast, the best option is to inline CSS directly into the page but lose caching benefits between pages?<p>Crafting a fast website is going to be messy and difficult for a good while still.
What? Multiplexing HTTP and other traffic was the entire argument justifying HTTP/2 and 3 complexity with multistatus etc. That server push was never going to work was clear from even a cursory look at the protocol spec and a minimal use case involving two subsequent page loads with shared resources. Was it really necessary for Google to foobar HTTP?
I'm going to sound like a broken record but HTTP/1.1 comet-stream works fine, just use "transfer-encoding: chunked" header in your response, write the length in hex followed by \r\n and then write the content with trailing \r\n\r\n, rinse and repeat.<p>It's simple, debuggable, inherently avoids cache-misses, scales (if you use non-blocking IO and joint concurrent capable language with OS threads).<p>It also avoids HTTP/TCP head-of-line because you're using a separate socket for your pushes.