Core Cloud Architecture · Part 3 of 13
Choosing How Your Code Runs: Compute Options
Several ways to run the same code, each trading control for speed in a different place.
Every cloud compute option runs your code. They differ in how much of the surrounding machinery you manage yourself: moving from a virtual machine toward a serverless function hands more of the operating system, the scaling, and the infrastructure to the provider.
Virtual machines
A virtual machine (VM) is a full, isolated operating system you provision, running on the provider's physical hardware alongside other customers' VMs. You choose the OS, install what you want on it, and are responsible for patching, scaling, and everything else an operating system needs. VMs offer the most control of any option here, and the most operational responsibility to go with it.
Containers
A container packages an application together with its dependencies into one portable unit, run by a container runtime rather than as a full separate operating system. Containers share the host OS kernel, so they start in seconds rather than minutes, and the same container image runs identically on a laptop, in CI, and in production, which retires "it works on my machine." Containers still need somewhere to run: on your own VMs, on a managed container service, or on Kubernetes (below).
MicroVMs: closing the isolation gap under the hood
A microVM (Firecracker, the technology AWS built and open-sourced, is the best-known example) gives each workload its own minimal virtual machine, complete with its own kernel, where a plain container shares the host's. That closes much of the isolation gap between a container and a full VM: a kernel-level bug or an escape attempt in one workload doesn't threaten every other tenant sharing the same host kernel, the way it could inside plain containers packed onto one machine. A microVM still starts in a fraction of a second, where a full VM needs tens of seconds to boot an entire operating system, which makes it fast enough to serve as the execution unit behind something as latency-sensitive as a serverless function. AWS Lambda and Fargate are built on microVMs for exactly that reason: VM-grade isolation for many tenants on shared hardware, without full-VM boot times on every invocation.
Serverless functions
A serverless function (AWS Lambda, and its equivalents) runs a single function in response to an event (an HTTP request, a message on a queue, a file upload) and the provider handles everything about where and how it executes. You write a function; you never provision a server, patch an OS, or explicitly manage scaling. Billing is typically per invocation and per unit of execution time, down to fractions of a second, so an idle function costs nothing to keep around. The trade-off is less control over the runtime environment, tighter limits (maximum execution time, memory, available languages and versions), and cold starts.
Serverless containers
A serverless container platform (Cloud Run, Fargate, Azure Container Apps) runs a container image without you provisioning or managing the underlying servers, combining a container's portability with a serverless function's operational simplicity. It's the middle of the spectrum: you package your app as a container, then hand scaling and infrastructure to the platform.
Kubernetes
Kubernetes is a container orchestration system: it schedules containers across a cluster of machines, restarts ones that fail, scales them, manages networking between them, and rolls out updates gradually. It orchestrates the same containers described above across many machines at once, so the execution unit underneath is still a container. The orchestration layer changes the operational picture enough to compare directly against the other options, and it's the option with the most moving parts to understand and operate (nodes, pods, deployments, services, ingress, and others), whether run yourself or through a managed offering (EKS, GKE, AKS) that handles the control plane for you.
Choosing between them
| Option | Startup speed | Operational complexity | Portability | Cost model | Control | Isolation |
|---|---|---|---|---|---|---|
| Virtual machines | Slow: provision, configure, patch | High: you own the OS | Low: provider-specific images and tooling | Pay for capacity, whether used or not | Highest | Highest: own kernel, hardware-enforced boundary |
| Containers (self-managed) | Moderate | Moderate to high, depending on the orchestrator | High: the image runs anywhere | Pay for the underlying compute | High | Lower: shares the host kernel with every other container on the box |
| Serverless containers | Fast | Low | High: a standard container image | Pay per request/execution | Moderate | High: most managed platforms run each instance in its own microVM |
| Serverless functions | Fastest | Lowest | Low: tied to the provider's function runtime | Pay per invocation, down to fractions of a second | Lowest | High: same microVM-per-workload isolation as serverless containers |
| Kubernetes | Slowest to first deploy | Highest | Highest: the same manifests run on any cloud or on-prem | Pay for the cluster's capacity | Highest, plus orchestration control | Lower by default: shared-kernel containers, unless paired with a microVM-backed runtime |
Equivalent services across the three major clouds
| Concept | AWS | GCP | Azure |
|---|---|---|---|
| Virtual machines | EC2 | Compute Engine | Virtual Machines |
| Serverless functions | Lambda | Cloud Run functions | Azure Functions |
| Managed containers | ECS | Cloud Run | Container Apps |
| Serverless containers | Fargate | Cloud Run | Container Apps |
| Managed Kubernetes | EKS | GKE | AKS |
Does this startup need Kubernetes?
Kubernetes is the option most likely to get reached for before it's earned, because it reads as the technically serious choice. What a correctly-run cluster costs is ongoing attention from people who could be building the product.
Any one of these is a legitimate reason to adopt it:
- Multiple teams need independent deploy cadences across many services, with enough of them that a serverless-container platform's simpler model has started to feel limiting.
- A multi-cloud or on-prem portability requirement: a current commitment to run the same workload across more than one environment.
- Workload shapes that don't fit serverless or managed containers: specialized scheduling needs (GPU pools, custom networking, fine-grained control over how pods are placed) that a simpler managed platform can't express.
- A platform team exists to own it: people whose job is running Kubernetes well.
One trade-off runs underneath all of these options: startup speed and low operational complexity on one side, control and portability on the other. Where a startup should sit on that line depends on the stage-and-risk framing from The Startup Lifecycle. A pre-seed company optimizing for how fast it can test whether anyone wants the product should default to speed and simplicity.