Three ways to run the same code
Once you've written an app, you have to run it somewhere. The cloud gives you three main options, and they exist on a spectrum from "you control everything" to "you control almost nothing and only pay when it runs": virtual machines β containers β serverless. None is universally best. The skill is matching the model to the job.
Note: Who this is for: Beginners who can write an app but aren't sure how to host it. We keep it practical, when to use which, and why.
The hotel analogy
| In the real world | In tech |
|---|---|
| π Renting a whole house | Virtual Machine |
| π¨ A room in a hotel | Container |
| ποΈ Room service, billed per use | Serverless |
How much of the building is yours, and how much is shared and managed?
A VM is a whole house, your own OS, your own everything, idle or not you pay rent. A container is a hotel room, you get an isolated space but share the building's plumbing (the host OS kernel), so it's lighter and faster to move into. Serverless is room service, you don't keep a room at all; you ask for something, it runs, you pay only for that, and it vanishes.
The trade-offs side by side
| Virtual Machine | Container | Serverless | |
|---|---|---|---|
| Startup time | Minutes | Seconds | Milliseconds |
| You manage | OS + runtime + app | Runtime + app | Just your code |
| Billing | Per hour, even idle | Per hour (cluster) | Per request / ms |
| Best for | Legacy, full control | Microservices, portability | Spiky / event-driven work |
| Watch out for | Idle waste, patching | Orchestration complexity | Cold starts, time limits |
Left = more control + always-on cost. Right = less ops + pay-per-use, with limits.
When to reach for each
Virtual machines
Pick a VM when you need full control of the operating system, you're running legacy or specialised software, or a workload runs constantly at predictable load. You trade convenience for control, and you own patching and scaling.
Containers
The modern default for most applications. Containers package your app with its dependencies so it runs identically everywhere, start in seconds, and pack efficiently onto hosts. The cost is orchestration: at scale you'll want Kubernetes, which has its own learning curve.
Serverless
Brilliant for spiky, event-driven, or infrequent work, an image-resize on upload, a webhook handler, a nightly job. You write a function, the platform runs it on demand and scales to zero when idle (you pay nothing). The catches: cold starts (first invocation after idle is slower) and time/size limits that make it a poor fit for long-running jobs.
Tip: A good default for a new app in 2026: containers for your main services, serverless for the glue (events, cron, webhooks). Reach for raw VMs only when something specifically needs them.
The same job, three ways
Notice how the amount of infrastructure you describe shrinks as you move right. A container needs an image:
Dockerfile
FROM node:20-alpine
WORKDIR /app
COPY package*.json ./
RUN npm ci --omit=dev
COPY . .
EXPOSE 8080
CMD ["node", "server.js"]
The same logic as a serverless function is just the handler, no server, no port, no Dockerfile. The platform supplies everything around it:
handler.py
# Runs on demand, scales to zero, billed per invocation.
def handler(event, context):
name = event.get("name", "world")
return {"statusCode": 200, "body": f"Hello, {name}!"}
Common mistakes that cost people hours
- Running idle VMs 24/7. Paying for a always-on house when room service would do. Match the model to the load.
- Reaching for Kubernetes on day one. Three containers don't need an orchestrator. Start simple; add k8s when the pain is real.
- Putting long-running jobs on serverless. Functions have time limits. A 30-minute batch job will get killed mid-run.
- Ignoring cold starts on latency-sensitive paths. If a user is waiting, a cold function start can hurt. Keep critical paths warm or on containers.
- Lifting a legacy app onto serverless unchanged. Serverless rewards stateless, short, event-driven design. Forcing a monolith into it fights the model.
Where to go next
The whole article in 5 lines
- VM = a whole house: full control, always-on cost, you patch it.
- Container = a hotel room: isolated, light, portable, the modern default.
- Serverless = room service: pay per use, scales to zero, but cold starts + time limits.
- Match the model to the workload; don't default to the most powerful (or most complex).
Common 2026 mix: containers for services, serverless for the glue.
Lessons: Compute Models and Serverless vs Containers.
Get hands-on: the Docker Lab and Kubectl Lab.
Related read: Docker vs Kubernetes: When to Use Each.
Originally published on TheSimplifiedTech, where this guide is interactive, with in-browser terminal labs and diagrams. Learn cloud and DevOps by doing, no videos.
Top comments (0)