AnyLearn
All lessons
Programmingbeginner

The Compute Spectrum: Machines, Containers, Functions

AWS offers several ways to run code, and they are not competitors so much as points on one spectrum trading control for operational relief. This lesson walks that spectrum from virtual machines to serverless functions, what you hand over at each step, the cold-start and state constraints that decide fit, and the honest cases where serverless is the wrong answer.

Updated · AI-authored, review-gated · how lessons are made

Not signed in: your progress and quiz score won't be saved.
Progress1 / 7

One spectrum, not four products

The compute options look like a menu of alternatives. They are better understood as one axis, ordered by how much of the machine you still think about.

At one end you rent a virtual machine and it is yours: you choose the operating system, install what you like, patch it, and it runs until you stop it. At the other end you upload a function and the platform decides when to run it, how many copies exist, and on what.

Every step along that axis makes the same trade in the same direction:

StepYou stop managingYou give up
Virtual machinesPhysical hardwareNothing yet
Managed containersThe host OS and patchingDirect machine access
Fully managed containersThe cluster's serversControl over placement and node tuning
Serverless functionsServers as a conceptLong-running processes, in-memory state, some runtime control

Key idea: there is no "best" point on this spectrum, and moving right is not progress. Each step buys operational relief and costs flexibility, so the right position is the furthest right you can go without losing something the workload genuinely needs.

Full lesson text

All 7 steps on one page, for reading, reference, and search.

Show

1. One spectrum, not four products

The compute options look like a menu of alternatives. They are better understood as one axis, ordered by how much of the machine you still think about.

At one end you rent a virtual machine and it is yours: you choose the operating system, install what you like, patch it, and it runs until you stop it. At the other end you upload a function and the platform decides when to run it, how many copies exist, and on what.

Every step along that axis makes the same trade in the same direction:

StepYou stop managingYou give up
Virtual machinesPhysical hardwareNothing yet
Managed containersThe host OS and patchingDirect machine access
Fully managed containersThe cluster's serversControl over placement and node tuning
Serverless functionsServers as a conceptLong-running processes, in-memory state, some runtime control

Key idea: there is no "best" point on this spectrum, and moving right is not progress. Each step buys operational relief and costs flexibility, so the right position is the furthest right you can go without losing something the workload genuinely needs.

2. Virtual machines, and why they are still everywhere

The virtual machine is the oldest cloud primitive and the least fashionable, which obscures how often it remains correct.

What it gives you is total control: any operating system, any kernel parameter, any daemon, any piece of licensed software that expects a real host, any GPU driver stack. What it costs you is that everything on that machine is now your responsibility, from patching to monitoring to replacing it when it fails.

Two aspects reward understanding early:

  • Instance families are specialised. Instance types are grouped by what they optimise, general purpose, compute optimised, memory optimised, storage optimised, and accelerated with GPUs. Picking a family that matches the workload's actual bottleneck is usually a larger win than picking a bigger instance in the wrong family.
  • Purchasing modes change the price enormously. On-demand charges per unit time with no commitment. Reserved capacity and savings plans discount heavily for a one or three year commitment. Spot instances offer spare capacity at a steep discount, with the condition that AWS can reclaim them at short notice.

In practice: spot capacity is the most under-used lever in cloud cost. Any workload that can checkpoint and resume, batch processing, CI runners, model training, rendering, can often run on interruptible capacity for a fraction of on-demand, and the engineering it requires, tolerating a killed worker, is engineering you wanted anyway.

3. Containers, and the two questions they raise

A container packages your application with its dependencies so it runs the same everywhere. The catalogue covers container mechanics in depth elsewhere; what matters here is that running them in a cloud raises two separate questions people routinely conflate.

Who schedules the containers? Something must decide which container runs where, restart failures, and roll out new versions. AWS offers its own orchestrator, ECS, and a managed Kubernetes, EKS. The trade is familiar: the native option is simpler and integrates tightly with the rest of AWS, while managed Kubernetes brings a large portable ecosystem and correspondingly more complexity to operate.

Whose servers do they run on? Independently of the orchestrator, the containers need machines. Either you run a pool of virtual machines and manage their capacity, patching and scaling, or you use Fargate, where AWS provides the compute per container and there is no cluster of servers to look after.

Gotcha: teams reach for managed Kubernetes because it is the industry standard and then discover the managed part covers the control plane, not the operational burden. Node upgrades, autoscaler tuning, networking plugins, ingress and the rest remain yours. Choose it for the ecosystem and portability, which are real; do not choose it expecting it to be less work than the simpler option.

4. Serverless: what actually happens on a request

Serverless functions invert the model. Instead of a process you keep running that waits for work, you supply code and the platform creates an execution environment when work arrives.

The consequence that shapes every design decision is the cold start. If no environment is warm, the platform must provision one, load your code and dependencies, and run any initialisation before your handler executes. That is the cold path. A subsequent request arriving while an environment is still warm skips all of it and runs the handler directly.

The practical rules follow directly from the diagram's two paths. Work done outside the handler happens once per environment, not once per request, which is why database connections and clients belong there. Large dependency bundles lengthen every cold start, so keeping the package small is a latency optimisation. And because environments are frozen between invocations rather than destroyed, background work started but not awaited may simply stop mid-flight and resume unpredictably later.

Scaling is the flip side: concurrency is achieved by running many environments at once, one per concurrent request, which is why serverless absorbs spikes gracefully and why a downstream database can be overwhelmed by a burst it never expected.

flowchart TD
A["Request arrives"] --> B["Is a warm environment free?"]
B --> C["Yes: run handler immediately"]
B --> D["No: cold start"]
D --> E["Provision environment"]
E --> F["Load code and dependencies"]
F --> G["Run init code outside the handler"]
G --> C
C --> H["Return response, environment kept warm"]

5. Where serverless is the wrong answer

Serverless is excellent for event-driven, spiky, stateless work, and it is oversold. The honest list of poor fits, each for a structural reason rather than a fixable one:

  • Sustained high-volume traffic. Per-invocation pricing is superb when usage is bursty and idle much of the time. A service running flat out around the clock is usually cheaper on reserved machines, because you are no longer paying a premium for elasticity you never use.
  • Long-running work. Functions have an execution ceiling. Work that legitimately runs for hours belongs in a container or batch job rather than being contorted into chunks to fit.
  • Latency-critical paths with strict tails. Cold starts put a fat tail on the latency distribution. Provisioned concurrency mitigates it by keeping environments warm, at which point you are paying for idle capacity, which was the thing serverless promised to avoid.
  • Anything needing local state or persistent connections. No in-memory cache survives reliably, and connection-per-environment behaviour is exactly what exhausts database connection pools during a scaling burst.
Predict first

Your serverless API scales beautifully during a traffic spike. Your relational database falls over. Why did the thing that scaled cause the failure?

6. Choosing a point on the spectrum

The decision is usually settled by four properties of the workload rather than by preference.

AskIf yes, lean toward
Does it need a specific OS, kernel, GPU driver or licensed agent?Virtual machines
Is traffic steady and high around the clock?Reserved machines or containers
Is traffic spiky, event-driven, or often near zero?Serverless functions
Does one request run for hours?Containers or batch
Do you already run Kubernetes elsewhere?Managed Kubernetes, for consistency
Is the team small with no platform engineer?The most managed option that fits

That last row deserves emphasis, because it is the one most often decided by fashion instead of arithmetic. Operating a cluster is a real ongoing job. A team of four shipping a product will get more from the managed option's constraints than from the flexibility of infrastructure nobody has time to tend.

In practice: mixing is normal and correct. A typical system runs its API on containers, its image processing on serverless functions triggered by uploads, its nightly aggregation as a batch job on spot capacity, and one virtual machine for the vendor appliance that refuses to be containerised. Uniformity is not a goal; fit is.

7. The property that outlives the choice

One design property matters more than the position you pick, and it is what makes the position changeable later: whether your compute is disposable.

Disposable means any running instance can be destroyed and replaced without ceremony, because it holds nothing that matters. No local state that is not also elsewhere, no manual configuration applied by hand, no uploaded files living only on that disk, nothing whose loss requires a person.

That property is what enables everything teams want from cloud infrastructure:

  • Autoscaling, which is just creation and destruction on demand.
  • Rolling deploys and instant rollback, which replace instances rather than mutating them.
  • Spot capacity, which is only safe if losing a worker is uneventful.
  • Recovery, since rebuilding from a definition beats repairing a machine nobody remembers configuring.

Key idea: the machine that cannot be destroyed is the one that eventually causes the outage, because everyone is afraid to touch it and its configuration exists only in its running state. Serverless enforces disposability by construction; on virtual machines it is a discipline you choose, expressed as infrastructure-as-code plus state kept in the storage services of the next lesson.

Check your understanding

The lesson ends with a 5-question quiz. Take it in the player above to see your score.

  1. What does each step from virtual machines toward serverless consistently trade?
    • Cost for performance
    • Control and flexibility for operational relief
    • Security for convenience
    • Portability for latency
  2. Which workload is the best fit for spot capacity?
    • A payment API with strict latency requirements
    • A stateful database primary
    • A batch job that can checkpoint and resume after a worker is reclaimed
    • A session store holding user login state
  3. Why should database connections and clients be created outside a serverless handler?
    • Because initialisation code runs once per execution environment rather than once per request
    • Because the handler cannot make network calls
    • Because AWS bills initialisation separately at a lower rate
    • Because handlers run in a restricted security context
  4. A serverless API scales smoothly during a spike and the relational database fails. Why?
    • Serverless functions bypass the database's query cache
    • The functions retried aggressively and amplified load
    • Cold starts caused timeouts that corrupted transactions
    • Each execution environment opens its own connections, so scaling out multiplies connections beyond what the database pool allows
  5. Why does disposable compute matter more than the point chosen on the spectrum?
    • Disposable instances are cheaper per hour
    • It is what makes autoscaling, rolling deploys, spot capacity and rebuild-based recovery possible at all
    • It is required for multi-region deployment
    • Non-disposable instances cannot be monitored

Related lessons

Programming
beginner

Networking and the Bill: Where the Surprises Live

Two things reliably surprise teams new to AWS: the network they must build before anything can talk, and an invoice driven by charges nobody chose deliberately. The two are connected, because moving data is where much of the cost hides. This lesson covers the virtual network primitives, the traffic charges that follow from them, and how to read a bill.

7 steps·~11 min
Programming
beginner

Storage and Data: Three Shapes, and Choosing a Database

Cloud storage looks like a long product list and is really three physical shapes, object, block and file, each with an access pattern it is built for and one it is bad at. This lesson covers those three, the difference between durability and availability that people conflate, what eleven nines actually means at scale, and how to choose a database by access pattern.

7 steps·~11 min
Programming
beginner

The Shape of AWS: Regions, Accounts, and Who Secures What

AWS offers hundreds of services, which makes it look like a catalogue to memorise. It is not. This lesson gives the four structures everything else hangs from: the physical geography of regions and availability zones, the account as a blast-radius boundary, IAM as the one gatekeeper every call passes, and the responsibility line between you and the provider.

7 steps·~11 min
AI
intermediate

Running an Agent: Runtime, Harness, and Session Isolation

An agent is a loop that runs for minutes, holds state, executes code it just wrote, and must not leak anything into the next user's session. This lesson covers what AgentCore Runtime provides that a container does not, why session isolation is the load-bearing guarantee, and where the managed Harness sits against bringing your own loop.

7 steps·~11 min