Skip to main content

Serverless

Editorial

Introduction

In the first week of June 2024, an artists' social app called Cara went from 40,000 users to 650,000. Its API ran on serverless functions, and the platform did exactly what the brochure promises: absorbed a 16× explosion with no capacity meetings, no 3 a.m. fleet-resizing, no outage — peaking at 56 million function invocations a day.

Then the invoice arrived: about $96,000. For the week.

Here is the thing this lesson wants you to see before anything else: those are not two stories. The rescue and the bill are the same property, seen from its two sides. Serverless made Cara's compute perfectly proportional to demand — and proportional means the bill scales with your success as smoothly as the capacity does.

The last two lessons split the deployable and priced the seams. This lesson shrinks the deployable one more step — down to a single function — and hands the servers, the scaling, and the idle to someone else's platform. What you get back is a completely different billing model, and learning when that inversion wins is the whole game.

In this lesson: what serverless actually is, the anatomy of a cold start (it's a boot sequence, not mystery latency), the billing inversion, the crossover — computed from real public prices, in both directions — and a simulator where you race the meter against the fleet under three shapes of load.

Scope: choosing between specific cloud compute products gets its own decision lesson later in this course (EC2 vs EKS vs Lambda: The Decision); containers and Kubernetes have their own section. And the style serverless functions most often plug into — events as the system's spine — is the next lesson (Event-Driven Architecture & P2P).

A single load curve shown twice, illustrating the two ways to pay for compute. The top panel, labelled the fleet, draws a spiky daily load curve inside a large flat rectangle labelled capacity you rent all month; the space between the curve and the rectangle's top is shaded and labelled idle you pay for, and a flat bill line reads the same every month. The bottom panel, labelled the meter, draws the identical spiky curve, but the shaded area now sits exactly under the curve itself, labelled you pay for the area under the curve, with a bill line that rises and falls with the spikes and a note reading zero when nothing runs. Between the panels a focal band carries the lesson's law: same load, two billing models — the fleet pays for the rectangle, serverless pays for the area. A bottom band completes the thought: proportional is glorious at idle and brutal at saturation. The figure communicates the billing inversion that defines serverless: cost stops tracking provisioned capacity and starts tracking work actually done, which is a bargain exactly when the rectangle would be mostly empty.

The Deployment Unit Shrinks Again

Watch what this section has been doing to the deployment unit. The monolith shipped everything as one artifact. Microservices cut it into capability-sized pieces. Serverless takes one more step: the unit becomes a single function — one handler, deployed alone, with no process of yours running anywhere until someone calls it.

That last clause is the radical part. In every architecture so far, you kept servers alive — provisioned, patched, scaled, paid for — whether traffic came or not. In serverless (Function-as-a-Service, to give it its precise name), the platform holds a pool of machines, and when a request arrives it finds — or creates — an execution environment for your function, runs it, and eventually reclaims it. Three consequences follow directly:

  • Scale-to-zero. No traffic, no environments, no cost. Your function is a file in storage, not a process on a box.
  • Scale-per-request. Each environment handles one request at a time. A hundred concurrent requests means the platform stands up a hundred environments — you wrote no autoscaling policy.
  • The platform owns the fleet. Patching, capacity, placement, the 3 a.m. page for a dying host — all of it moved across the counter.

What did you trade away? Control over the machine, the ability to keep anything in memory between requests, and — the subject of the next section — the guarantee that your process is already warm when a request shows up.

One vocabulary note before moving on: people also say "serverless" for managed services generally — queues, object stores, databases you don't operate. That wider spectrum is real (much of this course's data machinery lives on it), but this lesson means the compute slice: functions.

Anatomy of a Cold Start

"Cold start" gets said like a curse and understood like weather. It's neither — it's a boot sequence with four parts you can name, time, and mostly control.

When a request arrives and no warm environment exists, the platform builds one. On AWS Lambda — worth studying because its internals are public — that means booting a Firecracker microVM: a real, tiny virtual machine, started in under 125 milliseconds. Then the language runtime loads. Then your initialization code runs — imports, SDK clients, database connections — everything outside the handler. Then, finally, the handler serves the request.

Look at where the time actually goes. The microVM is fast and not yours to change. The runtime varies by language: Python and Node cold-start at roughly 200-400 ms at the median; Java historically took seconds to warm its VM — until snapshot-restore (SnapStart) cut it to around 180 ms by booting once and restoring from the snapshot thereafter. But the part with the widest variance is the third: your init code. A function that imports half an SDK and opens four connections at startup digs its own cold-start grave — which is why the platform caps the init phase at ten seconds. Cold starts are mostly won and lost in code you own.

Two more facts complete the model. Warm starts skip everything but the handler — the platform reuses idle environments for subsequent requests, until it reaps them (minutes of idleness, at its discretion; the reaping is why cold starts come back after quiet periods). And the cold start is a tax on the unlucky request: the first one after idle, or the leading edge of a burst that outruns the warm pool. Averages barely notice it. Your p99 finds it immediately — which percentile lens you learned in How Engineers Measure Systems.

Is the cold start a law of nature? No — it's the price of full-VM isolation. Cloudflare Workers makes the opposite trade: it runs code in V8 isolates — the browser engine's sandboxes — which start in under 5 milliseconds, effectively zero because the isolate loads while the TLS handshake is still in flight. The cost of that trade is a narrower world: JavaScript and WASM, tighter limits, no arbitrary binaries. Shrink the isolation and the start shrinks with it. There's no free lunch here, only a menu.

A horizontal timeline dissecting what actually happens during a serverless cold start, drawn as labelled duration bands. The first band, about one hundred twenty five milliseconds, is labelled microVM boots — a real, tiny virtual machine. The second band is labelled runtime loads, the language runtime starting inside the fresh machine. The third band, drawn widest and marked as the part you control, is labelled your init code — imports, SDK clients, connections — with a note that this is where cold starts are won or lost and a limit marker reading ten second cap. The fourth band, in a different colour, is labelled handler runs — the only part every request pays. Beneath the timeline, a second short bar labelled warm start shows a request skipping straight to the handler band, annotated the environment is reused — until the platform reaps it. A reference row gives real measured numbers: Python and Node roughly two to four hundred milliseconds at the median, Java historically seconds until snapshot restore brought it near two hundred milliseconds. The figure communicates that a cold start is not mystery latency but a concrete boot sequence, most of which is yours to shrink.

The Billing Inversion

Now the part that changes architecture decisions: what you pay for, and — more precisely — what you stop paying for.

Every fleet you've designed so far bills by capacity: you rent boxes sized for peak, and the meter runs whether requests come or not. Draw your daily load curve inside the rectangle of what you provisioned, and the white space between the curve and the rectangle's ceiling is money spent on silence. The previous lessons treated that as a fact of life.

Serverless bills by work. The unit is exquisitely small: on Lambda's published prices, $0.20 per million requests, plus $0.0000166667 per GB-second — memory times duration, metered per millisecond, for exactly the milliseconds your handler ran. (ARM shaves ~20% off; there's a permanent free tier of a million requests and 400,000 GB-seconds a month that real workloads blow through quickly.)

In the picture, the inversion is one sentence: the fleet pays for the rectangle; serverless pays for the area under the curve.

Say your handler runs 100 ms at 512 MB. One invocation costs $0.0000002 in requests plus 0.05 GB-seconds of compute — about a millionth of a dollar, all in. Nothing runs between requests, so between requests you pay nothing at all. That number feels unanswerable. Whether it actually is depends entirely on how many of those millionths you buy — which is the next section, and the reason this lesson exists.

The Crossover: Same Math, Opposite Verdicts

Run the same API through both billing models, twice, with nothing changed but the load's shape. Handler: 100 ms at 512 MB. Fleet side priced with this course's standing teaching constants — 1,000 requests/second per $70/month box, minimum two for availability (Single Point of Failure explained why two).

Scenario one: a quiet internal API. Averages 2 requests/second — busy at 10 a.m., near-silent overnight and on weekends. That's 5.2 million requests a month:

  • Requests: 5.2M × $0.20/M = $1.04
  • Compute: 5.2M × 0.1 s × 0.5 GB = 259,200 GB-s → $4.32
  • Serverless total: ≈$5.36/month. The two-box HA floor idles at $140/month. The meter is ~26× cheaper — because the fleet's rectangle was almost entirely empty space.

Scenario two: a saturated API. The same handler at a steady 1,000 requests/second, around the clock. Now it's 2.59 billion requests a month:

  • Requests: 2,592M × $0.20/M = $518.40
  • Compute: 2.59B × 0.1 s × 0.5 GB = 129.6M GB-s → $2,160.00
  • Serverless total: ≈$2,678.40/month. The equivalent fleet — two or three boxes running hot — costs $140-210/month. The meter is ~13-19× more expensive — because there is no idle left to avoid paying for.

Same prices. Same handler. Same arithmetic — you can redo every line of it from the public price sheet. The only variable that moved was the shape, and the verdict flipped by a factor of hundreds.

So retire "is serverless cheaper?" as a question. The real question is: what fraction of your provisioned time would a fleet spend idle? High idle share — spiky, bursty, business-hours, event-driven — and the meter wins going away. Saturation — steady, high, 24/7 — and the fleet wins by an order of magnitude. Somewhere between them sits a crossover point, and finding it for your own workload is a five-minute calculation you now know how to do.

Two priced scenarios proving that the same serverless arithmetic gives opposite verdicts depending on load shape. The left panel, labelled quiet API — idle-heavy, shows a load curve that is mostly flat near zero with small business-hour bumps, priced two ways beneath: serverless at about five dollars a month versus a two-box high-availability fleet at one hundred forty dollars, with the verdict twenty-six times cheaper and a green stamp reading the meter wins where the fleet would idle. The right panel, labelled saturated API — one thousand requests per second around the clock, shows a high flat load curve priced at about two thousand six hundred seventy eight dollars a month on serverless versus one hundred forty to two hundred ten dollars for the equivalent boxes, verdict roughly fifteen times more expensive, with a red stamp reading there is no idle left to avoid paying for. A bottom band names the rule: the shape of the load decides — both numbers come from the same public prices, one hundred milliseconds per request at half a gigabyte. The figure communicates that serverless is neither cheap nor expensive in itself; it is proportional, and proportionality wins or loses on idle share alone.

Drive It: Race the Meter Against the Fleet

The crossover is a number you should find, not memorize. Below, the same API is priced both ways, live, while you control the load.

Try this first: pick the spiky shape at a modest peak and watch the meter demolish the fleet — the fleet must size for a peak that almost never happens. Then switch to steady and drag the peak up to 1,000 req/s: watch the two cost bars cross, and keep going until the fleet is winning by 15×. Now stretch the handler's duration and memory and watch serverless get expensive faster — the meter charges for milliseconds and megabytes; the fleet doesn't care. The readout under the race tracks the cold-start picture for each shape: steady traffic stays warm, while the spiky shape pays init on every burst's leading edge — the latency half of the same trade you're pricing.

The Meter vs the Fleet — the same API priced both ways, live, under a load you shape. Pick one of three load shapes and watch a week of traffic draw itself: steady saturation, business hours, or spikes with silence between them. The fleet's capacity line rents the whole rectangle all week; the meter bills only the blue area under the curve. Drag the peak from one request per second to five thousand, stretch the handler's duration and memory, and two cost bars race to their real monthly totals computed from published prices — twenty cents per million requests plus a fraction of a cent per gigabyte-second. On the spiky shape at a hundred requests per second the meter reads five dollars and thirty-six cents against a hundred forty for the two-box fleet: twenty-six times cheaper, because the fleet must size for a peak that almost never happens. Switch to steady at a thousand requests per second and the same arithmetic flips: two thousand six hundred seventy-eight dollars against one hundred forty — the fleet wins nineteen to one, because there is no idle left to avoid paying for. A cold-start readout tracks the latency half of the same trade: steady traffic stays warm while every burst's leading edge pays init. The verdict panel names the winner and the why, and the footer states every constant so you can redo the math for your own workload.

What the Meter Doesn't Cap

Back to Cara, because both halves of that story are now legible.

The half that worked: a 16× user explosion in seven days, absorbed with zero capacity planning. No fleet resize, no load test, no war room. Scale-per-request means the platform stood up as many environments as the traffic demanded, minute by minute. A fleet sized for 40,000 users would have fallen over on day two; the meter didn't blink at 56 million invocations a day.

The half that hurt: nothing in the billing model saturates. A fleet has a natural cost ceiling — when the boxes are full, they're full; users see errors, but the bill stops climbing. The meter's whole virtue is that it never fills up — which means the invoice tracks your success with perfect fidelity, to roughly $96,000 for the week. Nobody had decided, in advance, what success was allowed to cost.

Two sober footnotes turn that story into engineering practice:

  • "Infinite scale" has posted quotas. A typical account defaults to 1,000 concurrent executions per region, growing at about a thousand new environments per ten seconds. Those are support tickets, not laws — but a viral moment can hit the throttle (429s) before it hits the headline number. Know your limits before your traffic finds them.
  • Budget alarms are architecture. With pay-per-use, a spending alert is the equivalent of a circuit breaker for your wallet — configured before launch, with a human decision attached: at what bill do we degrade, cache harder, or shed? The cost lessons at the end of this course (Cloud Cost Engineering) build this discipline out; here it's one sentence: proportional cost needs a proportional-cost plan.

The Constraint List, Honestly

Serverless buys its properties with real constraints. None is disqualifying; all are load-bearing in the decision.

Nothing survives between invocations. The platform may reuse your environment or silently discard it — so in-memory sessions, caches, and connection state are not yours to keep. Everything stateful externalizes to stores and caches, exactly the move Stateful vs Stateless: Where Does State Live? taught. Serverless is that lesson upgraded from advice to contract.

Executions are capped. Fifteen minutes, then the platform cuts you off. Long-running work restructures into queued steps — machinery this course covers in the messaging and pipeline lessons.

The p99 pays the cold-start tax — and the cure costs the disease. You can buy provisioned concurrency: environments kept permanently warm. Read that twice — you're paying for idle again. It's the fleet's billing model leaking back in, purchased per function. Sometimes worth it; never free.

Observing it is harder. A request now hops through managed services you can't SSH into; debugging is logs-and-traces or nothing — the observability section of this course stops being optional.

The architecture locks in more than the code. Your function body is portable; the event formats, triggers, permission wiring, and managed services around it are one provider's dialect. Migrations rewrite the wiring, not the handlers.

Weigh that list against what came off your plate: the fleet, the patching, the autoscaling policy, the idle bill, and the 3 a.m. host page. For the right shape of workload, it's the best trade in this section. For the wrong one, you just rented the world's most expensive steady-state computer.

The Decision This Lesson Enables

The rubric compresses to one primary test and two guards.

The shape test. Sketch a week of this workload's load curve. Estimate the idle share — the fraction of provisioned time a fleet would spend waiting. Above roughly three-quarters idle, serverless is almost certainly the answer; the meter charges nothing for the silence that dominates. Below roughly a quarter idle, the fleet is almost certainly the answer; do the two-line arithmetic anyway because now you can. In between, price both — it's five minutes.

The latency guard. If the workload is user-facing with a tight p99, price the cold-start tax: what fraction of requests land cold, and is ~200-400 ms acceptable on that edge? Async and event-driven work usually shrugs; interactive checkout paths usually don't — or they buy provisioned warmth and accept the partial return to capacity billing.

The blast-radius-of-success guard. Before launch, name the bill at which you'd want to know within the hour. Set the alarm. Decide the response. Cara's lesson in one line: the platform will happily scale to a success you haven't budgeted.

For the marketplace, the rubric lands cleanly: notifications — the module the previous lesson extracted across a clean async seam, spiky ×10 on game nights, idle most of the day — is born serverless. The steady checkout core, running hot around the clock against a tight p99, stays on the fleet. One system, both answers, each defensible with arithmetic — which is exactly what "trade-offs over templates" has meant all course.

Mental-Model Corrections

"Serverless means no servers." There are servers — real microVMs booting in under 125 ms. What changed is the rental agreement: by the millisecond of work instead of by the month of capacity, with the fleet on someone else's inventory.

"Serverless is always cheaper." It's cheaper where a fleet would idle. The same handler that costs $5 a month at 2 req/s costs $2,678 at a steady 1,000 req/s — against a $140-210 fleet. The meter beats the rectangle only when the rectangle is mostly empty.

"It scales infinitely." Two ceilings, not zero: quotas (a default of ~1,000 concurrent executions, ramping ~1,000 per 10 s) and the invoice, which scales with success without asking. Cara found the second one: ~$96k for a viral week.

"Cold starts make it unusable." Median cold starts for scripting runtimes are 200-400 ms, snapshot-restore tamed Java's seconds, and event-driven work barely notices. It's a p99 tax on latency-critical edges — a line item in the decision, not a veto over it.

"Serverless means our whole system goes serverless." It's a per-workload billing choice, not an identity. The marketplace runs its checkout on a fleet and its notifications on functions, and both choices came from the same arithmetic. Systems that pick per-shape beat systems that pick per-fashion — same verdict as the last lesson, one level down.

Key Takeaways

  • Serverless shrinks the deployable to a function and inverts the bill: from paying for capacity (the rectangle) to paying for work (the area under the curve), with scale-to-zero at one end and scale-per-request at the other.
  • A cold start is a boot sequence, not weather: microVM (~125 ms) → runtime → your init (the part you control) → handler. Warm reuse hides it; idleness and burst edges bring it back; your p99 is where it lives.
  • The shape of the load decides the economics. Same handler, same prices: ~$5 vs $140 for an idle-heavy API; ~$2,678 vs $140-210 at steady saturation. Idle share is the whole question, and the crossover is a five-minute calculation.
  • The meter never saturates. That's the rescue (Cara absorbed 16× growth unplanned) and the risk (~$96k/week, uncapped). Budget alarms are architecture; quotas are real; success needs a price you chose in advance.
  • The constraints are the contract: no memory between invocations, capped execution, cold-start p99 tax (with warmth purchasable at the cost of un-inverting the bill), harder observability, deeper lock-in.

The style palette now has three entries: everything integrated, capabilities split, and compute borrowed by the millisecond. The next lesson adds the connective tissue that serverless functions were practically invented to handle — Event-Driven Architecture & P2P: events as the system's spine, and what happens when nobody calls anybody directly at all.