> Technologies such as HTTP/2, websocket and SSE are clearly pointing in the direction of long-running client-server interaction

No, not really.

In modern web "application" load-balancer servers like Nginx, when the web server receives HTTP2 traffic, it will unwrap the HTTP2 stream into its individual consituent HTTP "sessions", and then make a separate upstream request for each session. From your application-server's perspective, you don't need to care about the "state" of HTTP2; it's just a transport-layer detail. If you wrote a (connectionless) REST API, its semantics survive entirely unchanged over an HTTP2 carrier. You just need an HTTP2 "tunnel terminator"—sort of like how stunnel(1) works for TLS, or how IPSec ESP tunnels are terminated by the kernel.

The same goes for websockets and SSE. You just deploy a reverse-proxy like https://github.com/fanout/pushpin, and then the client sees WebSockets or SSE streams, while your backends can treat the client as 1. a source of regular HTTP requests (translated from WebSocket messages); and 2. a webhook registrant (where the webhook is really just an endpoint on the reverse-proxy, and reverse-proxy sends the registration message when the client opens the stream), where you can then call that webhook with data—from any of your backends—to push a message into the relevant connection-oriented stream.

With a "smart" load-balancer/API-gateway layer like this keeping connection state for you, you can totally write your app entirely as a set of stateless functions running on stateless backends, while still allowing clients to "approach" the app statefully. (And I say this as someone who writes extremely stateful, connection-oriented Erlang service backends. Even my most fraught use-cases, that would never work or scale under e.g. PHP, do have a way to both work and scale under the FaaS+"smart API gateway" paradigm.)

And note as well that the "smart API gateway" isn't [or at least shouldn't be] something proprietary+nonstandard that a given FaaS provider is running for you (it's just a piece of software you can stand up an autoscaling cluster of); and nor does your API-gateway cluster need to live in the same cloud that your FaaS functions do. Your API-gateway is just a fancy web proxy making requests to upstreams; if you think of it like your API-gateway being your web-app, and the upstreams being third-party SaaS vendors you make API calls to during the request lifecycle, you'll have the right mental model for what ops with a FaaS looks like.

---

That being said, I don't necessarily disagree with this:

> For me the biggest shortcoming in serverless is that it is actually a poor fit for modern interactive web apps (and apps in general) with a constantly changing state.

I wouldn't call Serverless a poor fit, personally, but interactive apps are certainly not the simplest, most idiomatic use-case for Serverless architecture.

Instead, Serverless is most idiomatic when used to build

1. the "Command" and "Query" layers of an event-streaming CQRS architecture; or

2. the map and reduce steps of ETL pipelines (i.e. the "DoFn"s, in Apache Beam parlance; or the "design documents" in CouchDB parlance.)

In both paradigms, you're already pretty much restricted from manipulating any sort of global state anyway, so you don't lose anything by using FaaS functions rather than long-running code. It's a much more natural fit.

(And the interesting thing is, you can frequently rearchitect an "interactive web-application" into a CQRS system + a bunch of async ETL pipelines. Twitter is essentially this kind of thing, for example. So is your bank.)

---

Still, admittedly, one thing you lose with Serverless is the ability to keep local computations cached.

I think Lambda, at least, is moving toward an architecture that will address this somewhat, with Lambda "functions" now essentially being Docker containers that do HTTP request/response over their stdio. If that Docker container were required to be able to stick around for multiple HTTP requests, you'd get something that's a lot more like "distributed FCGI" than "distributed CGI", and you'd be able to go back to the same sort of local in-memory caching that you see in e.g. Ruby/Python web-apps.