Server, Serverless, and Container — The Application Server Tier

This article is part of the IT Foundations course, which builds up from scratch the practical IT knowledge you need at a minimum for programming and vibe coding.
The difference is how long the program that does the work stays running. Diagrams let you tell apart the form that keeps running and waits, the form that runs only on a request, and containers, which run with their own runtime on a single OS.

This article covers the three forms for running the application server tier.

They are always-on, which keeps one server running; serverless, which runs only when a request arrives; and containers.

The difference is how long the program that does the work stays running.

Because that time differs, so does how you add capacity when requests increase and what you have to prepare yourself.

Three ways to run it, split by how long it stays running
Running the appserver tierKeep running withno requestsRun only when arequest arrivesAlways-on serverContainerServerless
From the one node on the left, the split is whether it has to be running when there are no requests. The top keeps running; the bottom runs only when it is called.

An always-on server keeps running and waits for requests

You never know when a request will arrive, so you start server.js first and leave it waiting as a process — one program that has been started and is running.

Leaving that process in place instead of ending it is always-on: keeping the program running so it can accept a request at any time.

Server listening on port 3000
Press Ctrl+C to stop

The first line shows it listening for requests on the port number you chose.

As the second line says, the process does not end until you take an action to stop it.

What arrived at that timeThe server.js processWhat goes back to the web server tier
9:00 you start itStarts up and begins listeningNothing goes back yet
9:05 a /reservations requestReceives it as is and looks up the reservations3 reservations
9:06 nothing arrivesKeeps waiting instead of endingNothing goes back
What is inside a server that keeps running
The computer you keep running
The node process (started with node server.js)
  • Listens for requests on port 3000
  • Does not end until you take an action to stop it
server.js — the file holding the booking app's processing
  • Contains the handling for requests that arrive at /reservations
  • Asks the database tier for the number of reservations
The OS, and the node you installed yourself
  • You install node from the official site
  • You apply the OS updates yourself too
The outer box is the computer you keep running. Inside it the node process listens, and inside that the server.js you wrote is loaded.

The innermost server.js is not the only thing you prepare yourself.

You also prepare the computer you keep running, the OS on it, and node.

This is the big difference from serverless, which comes next.

Inside the box is the one machine you prepare and keep running.

The process does not end while no requests are arriving; it waits with the port held open.

Always-on stays running until you stop it

An always-on server is one you start in advance and leave waiting for requests to arrive.

node server.js is what starts it, the process does not end until you take an action to stop it, and you prepare the computer you keep running, the OS, and node yourself.

Serverless runs the processing only when a request arrives

Serverless is the form in which the program that does the work runs only when a request arrives and stops once the work finishes, and with it you do not run a listening process yourself.

What you register is a single file such as handler.js, and the unit you register is called a "function".

With serverless, what the provider prepares and what you put there
The cloud provider's system
The part that receives a request and calls the function
  • Receives the requests that arrive
  • Decides how many run at once
The runtime prepared for each request
  • The provider prepares the OS and node
  • Stops once the work finishes
handler.js — the file holding the booking app's processing
  • Handles only the one request that arrived at /reservations
  • There is an upper limit on how long it can run
The outer box is the cloud provider's system. The upper box is the part that receives requests, and it is always running. The lower box is the runtime prepared for each request, and your handler.js sits inside it.

The only thing you touch is the innermost handler.js.

The provider prepares the boxes outside it, and the provider also applies the OS and node updates.

Who prepares what is covered in the article on on-premises, rented servers, and the cloud.

While no request has arrived, handler.js is not running.

A runtime is prepared for each request and stops once the response is returned.

This is the difference from always-on, which stays running until you stop it.

Serverless runs only when it is called

Serverless is the form that starts the processing after a request arrives and stops it once the response is returned.

The only thing you put there is handler.js, and the provider prepares the runtime that runs it for each request.

How you add capacity when concurrent requests increase differs

The number of requests arriving at the same time changes with the time of day.

Adjusting to that is scaling — increasing or decreasing the number of things doing the work to match the volume of requests.

Start with three requests arriving at a serverless setup at the same time.

When three arrive at once, three runtimes start up too
A's request to/reservationsB's request to/reservationsC's request to/reservationsRequest receiverprovider's systemRuntime 1handler.js runsRuntime 2handler.js runsRuntime 3handler.js runs
The three on the left are all requests to the same /reservations. After the middle receives them, one runtime is prepared per request.

Up to the number the provider allows to run at once, no request is left waiting.

You do not do anything yourself to add capacity.

An always-on server needs the same roles filled, but different parties fill them.

What fills the same role in always-on and in serverless
===Listen forrequestsnode process waitson port 3000The provider'sreceiving partRun the processingRuns server.js inthe same processPrepares a runtimeto run handler.jsAdd moreYou add processesor machinesProvider's systemadds them at once
The left column is the role, the middle column is an always-on server, and the right column is serverless. The two joined by a double line do the same thing; only who does it differs.

What changes is whether you decide to add capacity yourself or leave it to the provider's machinery.

Once the number has grown, the same person's requests do not always reach the same one, so stateless is required — one run of the processing holds no value remembered from a previous run.

Whether the second request can read a value the first one remembered depends on where you put that value.

A value you also use on the next request is saved to the database tier and read back from there.

The same holds on an always-on server: once you add processes, the value does not remain in the other processes.

How capacity is added, and where values are kept

When concurrent requests increase, with always-on you add capacity yourself, and with serverless the provider's system does it for you.

Once the number has grown, the same one does not always answer both requests from the same person, so a value you want to use again goes to the database tier, not to local memory.

Containers run on a single OS, and you pick among the three by whether you need always-on

The third form, the container — a format that bundles the app, its runtime, and the files it needs into one and runs it on a different computer with the same setup — stays running for the same time as an always-on server.

What differs is that the runtime is not installed on the computer but wrapped up together with the app.

The same three apps on three machines, and in containers on one machine
One machine prepared per app
What you prepare
  • Three computers
  • Three OSes
  • Node.js 18 / Python 3.11 / Node.js 20 installed on separate machines
One machine shared through containers
One computer, one OS — three containers run on it
Container 1
  • One process
  • Node.js 18
  • server.js
Container 2
  • One process
  • Python 3.11
  • batch.py
Container 3
  • One process
  • Node.js 20
  • admin.js
The top prepares one machine per app, so it needs three machines and three OSes. The bottom runs three containers as one process each on a single OS, so one machine and one OS are enough.

There is one OS, and each container runs on it as a single process.

The runtimes sit separately inside the containers, so whatever the container next to it uses has no effect.

The share of hardware used to run something, such as CPU and memory, is a resource.

The top runs three OSes, while the bottom shares a single OS, so the same hardware can hold more apps.

You can run more on the same number of machines, and it costs less to keep them running.

No new OS is started, so the time until it begins running is shorter too.

Running two on the same machine: where the runtime goes changes the result
Want Node 18 andNode 20 runningon one machineInstall runtimeinto the OSOnly one node fitson a machineYou must settleon one of themBundle runtime andapp in a containerEach container hasits own nodeBoth run side byside as they are
The left is what you want to run. The upper path installs the runtime on the computer; the lower path bundles it into a container. On the same machine, where you put the runtime changes the result.

One OS can hold only one node, but with containers you can run them side by side with separate nodes.

The runtime is separate for each app, so raising the version on one leaves the other running.

The bundled set of files is a container image — the app, the runtime, and the files it needs bundled into one — and Docker is the best-known software for building and running one.

The side that runs it only receives this image and starts it.

The same single image gives the same setup wherever you run it
App, runtime, andthe files it needsContainer imagebundled into oneYour own computerPublic serverCoworker's PC
The container image is the three on the left bundled into one. The three places on the right start that image as it is, so you do not have to install the runtime again.

Even when the place you run it changes, what starts is the same single image.

You do not have to install the runtime again on the public server, so you can publish the same setup that ran on your own machine.

The dividing line when you choose is whether it has to be running when there are no requests.

The other dividing line is how much you can fit on one machine.

Whether you need always-on splits the three ways of running
Processing to runMust run even withno requestsRuntime goes onthe computerAlways-onserverRuntime bundledinto oneContainerOnly needs toanswer requestsRun only whencalledServerless
From the one node on the left, the split is whether it has to run when there are no requests. The upper two lines keep running once started, and the lower one starts running after a request arrives.

On the upper two lines, the process stays running even when there are no requests.

Those two split by whether the runtime is installed on the computer or bundled together with the app.

The two always-on forms keep running through the time when no requests arrive as well.

With serverless, what is counted is only the time it ran and the number of times it was called.

While requests are sparse, that difference shows up directly.

Choose by how long it stays running

The first split is whether it has to be running when there are no requests.

If it does not, serverless; if it does, an always-on server or a container.

Containers share a single OS between apps, so you can fit many on the same hardware and hold down the cost of keeping them running.

You also pick a container when you want the setup on your own machine and on the published server to match.

QUIZ

Knowledge Check

Answer each question one by one.

Q1How does the length of time the program that does the work runs differ between an always-on server and serverless?

Q2When do you use a container?

Q3What do you do when you want to use a value you put in memory partway through the processing on the next request as well?