Subject: In defense of PUSH

From: Matthew Phillips <[email-masked]>
Date: Fri, 31 Aug 2018 14:19:12 -0400

I recently saw this talk (
https://www.youtube.com/watch?time_continue=8041&v=Um5HHZkXGg4) given by
Chrome engineers on experimenting with disabling H2 PUSH, where they
concluded that sites currently do not see a benefit from using PUSH. At the
end of the presentation they mentioned the idea of  disabling PUSH for
everyone. I wanted to reach out to this list to present a case in favor of
PUSH.

The talk focuses on the use of PUSH as a mechanism to speed up initial load
time. There has been much written about this in the past, and I fully
believe the conclusion that it is difficult to make work for that use case.

First I'd like to point out the obvious; PUSH is still a very new
technology and few sites are even attempting to use it. So it shouldn't be
any surprise that few are using it successfully. It is competing against
techniques that have been refined for over two decades; CDNs, caching
strategies, Preload, resource prioritization / deferring, etc. It will take
time to figure out where PUSH fits in with these strategies. The results
suggest that it is not a replacement for them.

With that being said, there are use-cases for PUSH aside from pushing
cacheable static assets. PUSH is of great value for non-cacheable dynamic
data. I'd like to present a couple of use-cases to illustrate the point.

With modern web pages preferring to render content in the client, rather
use server rendering, load performance is better measured by "time to
interactive" (
https://developers.google.com/web/tools/lighthouse/audits/time-to-interactive).
This goes beyond the time it takes to load HTML, CSS, and JavaScript as
this talk focuses on. Pages also now need to make additional requests for
data. This is where PUSH can help.

As a simple example consider a chat application. The app might elect to use
a technique such as the app shell model (
https://developers.google.com/web/fundamentals/architecture/app-shell)
where only the skeleton of the application is sent to the browser, which
then makes another request for chat messages once JavaScript is ran. This
technique works particular well for applications with offline support. The
application is not interactive until those messages are loaded. PUSH can be
helpful here; the server can create a stream of messages and PUSH them
along with the initial HTML. By the time the JavaScript has ran and
connects to that PUSH stream it can immediately start displaying messages.
And with new streaming APIs in the browser, it can stay connected to this
stream for the lifetime of the application, receiving new messages as they
come. This prevents needing to use WebSockets and the complexity they bring.

In a slightly more complex example, my company has been envisioning an
alternative to HTML streaming that utilizes H2 PUSH. When I say HTML
streaming I am talking about the technique of sending HTML in chunks, as
database results come in, until the fully page is sent out. One problem
with HTML streaming is that the top of the page isn't always ready before
parts further down.

As an example, consider an ecommerce site that shows a shopping cart, with
a count, in the page's header, and then lists products, such as shoes, in
the main part of the page. The database query for the list of shoes is
likely to be faster than the query for the cart count. It is likely a
simpler query with proper indices, and if streaming is supported by the
database it can be loaded even quicker. Whereas the cart might require a
more complex query with multiple joins. With HTML streaming the slowest
database request blocks rendering anything below it.

A newer idea we've been pursuing is to send an app shell (like discussed
above) and then further updates occur as mutation instructions through an
H2 PUSH stream. The client connects to this stream and applies the
mutations via DOM apis. In this case we can start displaying the product
listing for shoes while the user's cart data is still being loaded.

H2 PUSH is critical for doing this. Without the ability to push this
mutation stream, it doesn't have as much of an advantage over using HTML
streaming. I wrote about research we did into this idea last here. It
includes non-scientific data, but it's worth giving some consideration.
https://www.bitovi.com/blog/utilizing-http2-push-in-a-single-page-application
.. You can see a demo of it working here:
https://www.youtube.com/watch?v=3smwqZHJ68I

In conclusion, please don't kill PUSH! Give web developers more time to
come up with creative uses for it aside from the asset loading case.

---

From: Andy Green <[email-masked]>
Date: Sat, 01 Sep 2018 03:40:09 +0800

>come. This prevents needing to use WebSockets and the complexity they

Ws is nice and simple on the JS side... it's only complicated on most servers because it's treated as an alien bolted-on protocol.

Do you really need "new streaming apis in the browser" or isn't it "native h2 ws" that can expose asynchronous messages using h2 streams, PUSHed or not, as the transport?

When ws-over-h2 was discussed I suggested supporting PUSH, but the consensus wanting to see it implemented wouldn't support the extra complexity, leaving it for a putative future native ws replacement.

With h1 ws it's expensive for the client to set up a new connection and tls back to the server after it received the script telling it to do so, ws-over-h2 improves it, but native h2 ws using PUSH could be right there already with the first message as soon as the script realized it wanted it.  At the cost of the complexity of teaching the server that fetching xxx implies pushing yyy.

Although you seem to write off ws, its async atomic message focus and apis seem to match what you're trying to do (and have a story for h1 compatibility).   If you're not aware of it, the latest version is here

https://datatracker.ietf.org/doc/draft-ietf-httpbis-h2-websockets/

>with HTML streaming is that the top of the page isn't always ready

A lot of applications want atomic JSON messages rather than chunks of html, ws semantics in JS handle this well.  Browsers seem to want to get to the loaded event triggered by definitively having received all the pieces so the layout is finalized, the 'dribbling html stream' delays that indefinitely.

>mutation stream, it doesn't have as much of an advantage over using

I think it's fair to say you want ws style atomic messages, if you could get them via h2 PUSH that'd be ideal.  The neccessity for ongoing, async messages are the real issue, PUSH is only a - desirable - optimization.

-Andy