Tutorials › Core Cloud Architecture › Choosing How Your Code Runs: Compute Options

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

OptionStartup speedOperational complexityPortabilityCost modelControlIsolation
Virtual machinesSlow: provision, configure, patchHigh: you own the OSLow: provider-specific images and toolingPay for capacity, whether used or notHighestHighest: own kernel, hardware-enforced boundary
Containers (self-managed)ModerateModerate to high, depending on the orchestratorHigh: the image runs anywherePay for the underlying computeHighLower: shares the host kernel with every other container on the box
Serverless containersFastLowHigh: a standard container imagePay per request/executionModerateHigh: most managed platforms run each instance in its own microVM
Serverless functionsFastestLowestLow: tied to the provider's function runtimePay per invocation, down to fractions of a secondLowestHigh: same microVM-per-workload isolation as serverless containers
KubernetesSlowest to first deployHighestHighest: the same manifests run on any cloud or on-premPay for the cluster's capacityHighest, plus orchestration controlLower by default: shared-kernel containers, unless paired with a microVM-backed runtime

Equivalent services across the three major clouds

ConceptAWSGCPAzure
Virtual machinesEC2Compute EngineVirtual Machines
Serverless functionsLambdaCloud Run functionsAzure Functions
Managed containersECSCloud RunContainer Apps
Serverless containersFargateCloud RunContainer Apps
Managed KubernetesEKSGKEAKS
GCP uses Cloud Run for both the managed-containers and serverless-containers rows: one service where the other providers ship two products.

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:

Every trigger above is a fact about the present. "We might need it later" is a guess about the future, and it's the reason most premature clusters get built. A ten-person startup running one product for one set of customers, with no platform team and no multi-cloud requirement, gains nothing from Kubernetes today that a serverless container platform doesn't already provide at a fraction of the operational load, and can adopt it later, once a trigger shows up.

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.