First, there were bare-metal servers (then known as just "servers"). It was the future. You could host a website made of a few pages, which others could see by typing in your website address into their browsers. It was amazing, and it was the future.
Then, there were virtual machines. You could install a hypervisor on your bare-metal server (or "server") and split it into lots of little, isolated virtual servers. Thus, you could isolate various components of your infrastructure, leading to more secure, stable, and flexible web applications. It was the future. But it was more complex, despite its advantages.
Then the cloud came along. Now someone else managed your bare-metal servers and your hypervisor, so you kept all the advantages of virtual servers, but lost most of the disadvantages. You also got other advantages - you could easily connect up your virtual servers to independent private networks, for example. It was the future.
The cloud brought along with it many other advances. Products started being offered as services, like storage, database management, log aggregation, telemetry, and alerting. Suddenly we did not have to run any servers at all to be able to get these features in our infrastructure. It seemed we were on the verge of losing the burden of managing any servers at all, virtual or bare-metal, just like we lost the burden of managing bare-metal machines and hypervisors when the cloud came along.
Then a company called Docker released a piece of software that let you package an application up with all its dependencies as a full operating system image, but run it as a normal operating system process. It was hailed as the future. No more dependency management during development when sharing code between developers, or at deployment time! Parity between development and production environments! Uniform deployment mechanism regardless of which framework or language you used!
However this meant we now had an even greater burden on our hands. Not only did we have to manage the virtual machines hosting the containers, we had to manage another layer of operating systems which were installed in the containers. To do containers properly, we had yet another layer too - the container orchestration layer. It was like we had stepped back in time to a world where we had to manage our own bare-metal servers, the hypervisors installed on them to enable virtualization, and the virtual machines themselves.
Thankfully, the cloud enabled another model for running our applications - the "serverless" model. We just had to upload our code to a service like AWS Lambda, or Azure Functions, and the cloud provider would run it for us. We would not have to worry about managing any servers or containers at all. Underneath the hood, they were using containers-managed-by-container-orchestration-on-virtual-machines-managed-by-hypervisors-on-bare-metal-servers, but we did not have to touch ANY of that. Our code was kept running reliably and securely by a team of the best engineers in the world.
This truly is the future. Unfortunately we are not there yet. Creating a full serverless application is currently an exercise in frustration due to a lack of tooling. Whereas server-based frameworks have been in development for years, serverless frameworks have just started to be developed, and are quite raw in their offerings. More work needs to be done.
There is currently no way to run a full stack test of a serverless app locally - it has to be deployed first. Most languages do not have a framework at all - the "Serverless Framework" has a growing list of supported languages, but it offers little more than a coherent way to organize and deploy your code. It does not enforce an opinionated paradigm to accelerate development, like Rails, Django, or Spring. We need development frameworks, monitoring and debugging tools, and everything else we currently have in our server-based world.
Like all futures, this will not just come. We need to work at it. But when we get there, we will be in a sweet place.
Until something else comes along.