2.4 Serverless functions
Describes the cloud compute landscape as of August 2026
What this is and why it exists
Serverless is a bad name for a real idea: there are still servers, but none of them is yours to choose, patch, size or restart. You hand the provider a function and a rule for when to run it, and you are billed for the milliseconds it runs. That removes a category of work entirely — and adds a set of constraints that decide whether it fits your problem or ruins it.
The vocabulary
- Function — a single piece of code with one entry point, deployed on its own; Amazon calls the service Lambda, Azure calls it Functions, Google calls it Cloud Run functions.
- Trigger — the thing that causes a run: an HTTP request, a file appearing in storage, a message arriving, a timer.
- Event — the data describing what happened, handed to your function as its input.
- Invocation — one run of your function, for one event.
- Concurrency — how many invocations are running at the same moment; the platform starts more copies as needed.
- Cold start — the delay when a request arrives and no warm copy exists, so one must be created first.
- Timeout — the hard limit on how long one invocation may take before it is killed.
- Stateless — nothing your function keeps in memory or on disk is guaranteed to be there next time.
The mental model
The contract is small and worth memorising: an event goes in, your code runs, a result comes out, and the platform handles everything else — the machine, the operating system, the patching, the scaling, and the shutting down when nobody is asking. In exchange, three constraints are absolute.
First, invocations are independent. The platform may run one copy or four hundred, on any machines it likes, in any order. Anything you put in a variable between requests might survive, and might not — so it is a cache, never a store. Real state goes somewhere designed for it: a database, object storage, or a cache service. The most common serverless bug is code that worked in testing because one warm copy handled every request, and broke in production the moment two copies existed.
Second, there is a clock. Every platform kills an invocation at its timeout, which makes long jobs a design problem rather than a configuration one. The pattern is to split the work: a function that receives the request and records the job, and further runs that process pieces of it, each finishing well inside the limit.
Third, cold starts are real but frequently misunderstood. When a request arrives and no warm copy exists, the platform must create one, and that costs a few hundred milliseconds up to a couple of seconds depending on the runtime and the size of your dependencies. Traffic that arrives steadily rarely pays it; traffic that is rare, spiky, or spread thinly across many different functions pays it often. A large bundle of libraries makes it worse, which is one of the few times "delete unused dependencies" has a directly measurable payoff. And note the coupling most people meet by surprise: on these platforms memory and processor are one dial — asking for more memory also gives you more processor, so a function that is slow rather than memory-hungry can still get faster and, because it finishes sooner, sometimes cheaper.
Which leads to the honest economics. Serverless is dramatically cheaper for work that is intermittent — a nightly report, a webhook nobody calls at four in the morning, a feature used a hundred times a day — because idle costs nothing at all and there is no machine to pay for while waiting. It is dramatically more expensive for work that is steady and heavy, where a machine you rent by the hour is amortised across every second and a per-invocation price is not. The crossover is a real calculation you can do, and the shape of the answer is stable even though the numbers change: constant load favours machines, bursty and sparse load favours functions.
What you should now be able to explain or do
State the function contract in one sentence. Explain why a value cached in a module-level variable is a performance trick and not a store, and name the bug that follows from treating it as one. Redesign a long job that exceeds a timeout into pieces that do not. Say who pays cold-start cost and who mostly does not, and two things that make it worse. Explain the memory-and-processor dial. Given a workload description, argue for serverless or for a rented machine on cost, and say what would change your answer.
Check yourself
Your function stores a counter in a variable at the top of the file. It works locally and gives wrong numbers in production. Why?
Because invocations are independent and the platform runs many copies. Each copy has its own variable, and copies come and go. That variable is a cache at best; a counter belongs in a database.
What is a cold start, and which workloads pay for it most?
The delay while the platform creates a new copy because no warm one exists. Sparse, spiky or widely-spread traffic pays it often; steady traffic mostly does not. Large dependency bundles make it worse.
A job takes twenty minutes and the platform's timeout is shorter. What is the fix?
Split it. One entry point records the work to be done, and further invocations each process a piece that finishes well inside the limit. Raising the timeout is not available beyond the platform's ceiling.
Why can giving a function more memory make it cheaper?
Because memory and processor are a single dial — more memory means more processor, the invocation finishes sooner, and you are billed for the time it ran. Faster can cost less.
Name one workload where serverless is much cheaper and one where it is much more expensive.
Much cheaper: an endpoint called a few hundred times a day, where idle is free. Much more expensive: a service under constant heavy load, where a rented machine spreads its hourly cost across every second and per-invocation pricing does not.
Go deeper
We haven't checked most of these for screen reader use yet.