Skip to main content
PProfileMatch

Cloud Compute and Storage Choices: VMs, Containers, Serverless, Object

Cloud ComputingLesson 3 of 46 min read

What you'll learn

  • Compare virtual machines, containers, platform services and serverless functions
  • Match object, block, file and database storage to the data they suit
  • Sketch a complete architecture for a small web product and justify each choice
  • Do a back-of-envelope cost estimate and see how elasticity changes it

On this page

  1. Compute: four ways to run your code
  2. Storage: the right container for the data
  3. Putting it together: the ticket-booking architecture
  4. A back-of-envelope cost estimate (illustrative only)
  5. Common mistakes
  6. How this shows up in real projects and interviews

A regional theatre company wants to sell tickets online. Most of the year a few hundred people visit per day. When a famous show goes on sale, thousands arrive in the first ten minutes, all fighting for the same front-row seats. This one product needs steady everyday capacity, a short enormous spike, strict correctness for seat reservations, and cheap storage for posters and PDF tickets. No single compute or storage option serves all of that, which makes it a good case for learning how to choose.

Compute: four ways to run your code

OptionWhat you manageScales byBest forWatch out for
Virtual machineOS, patches, runtime, app, scaling rulesAdding VMs (minutes)Legacy apps, special software, full controlIdle machines still bill; you do the patching
Containers on a managed serviceYour container image and its configurationMore container copies (seconds to a minute)Web apps and APIs packaged for portability; see Docker and KubernetesLearning curve for orchestration if self-managed
Platform service (PaaS)Just the code and settingsPlatform auto-scalingStandard web apps with little ops staffPlatform limits; some lock-in
Serverless functionA function and its triggersPer event, automatically, down to zeroSpiky or infrequent work: file processing, webhooks, scheduled jobsTime and memory limits; cold start delay on first call; harder local debugging

There is no best option, only a best fit per component. A useful rule of thumb is to match the shape of the workload: steady and long-running work suits containers or VMs, bursty event-driven work suits functions, and when nothing special is needed a platform service means the least work. Serverless is not magic: you still pay per invocation and for the time your code runs, so a function called constantly can cost more than a small always-on container.

Storage: the right container for the data

Storage typeAccess modelGood forNot good for
Object storageWhole objects by key over HTTP; very durable; effectively unlimitedImages, videos, backups, PDFs, logs, static website filesFrequent small in-place edits; acting as a database or a mounted disk
Block storageA raw disk attached to one VM; fast random reads and writesA VM's system disk; a self-managed database's data filesSharing between many servers; cheap long-term archives
File storageA shared folder many machines mount at onceContent that multiple servers must read and write as filesHuge internet-scale distribution; ultra-low-latency databases
Managed databaseQueries over structured data with transactions and indexesOrders, users, seat inventory, anything needing consistencyLarge binary files such as videos

For databases, relational versus non-relational is a design question covered in Databases in System Design. For seat inventory the theatre needs transactions, so a managed relational database is the natural choice, with the provider running backups and a standby in a second zone.

Putting it together: the ticket-booking architecture

Ticket-booking site: one region, two zones
  Browser
    |
  [CDN] ---- posters, JS, CSS ----> [Object storage: assets]
    |
  [Load balancer]  (spans zones A and B)
    |
  [Web/API containers x2..8]   <- scale on request rate
    |        |
    |        +--> [Queue] --> [Function: PDF ticket + email]
    |                                  |
    |                         [Object storage: tickets]
    |
    +--> [Cache: seat holds, 5-min TTL]
    |
  [Managed SQL database]
     primary (zone A) + standby (zone B)
     automated daily backups, point-in-time recovery

Every box has a reason. The CDN and object storage serve posters so the app servers never touch them. Containers behind a load balancer run the booking logic and scale with traffic, and because they are stateless any of them can serve any request. The seat-hold timer lives in a cache so that tens of thousands of "hold this seat for five minutes" operations do not hammer the database. The only authoritative record of who owns which seat is the transactional database. And the slow, bursty, non-urgent work, building a PDF and sending an email, goes through a queue to a function so that a slow email provider can never slow down checkout. The same queue-and-worker idea appears in the Apache Kafka course when volumes get larger.

A back-of-envelope cost estimate (illustrative only)

Cost reasoning should happen before building, using rough numbers. The program below uses invented prices in made-up units, not any provider's real rates, to show the structure of an estimate: list the components, multiply a unit price by quantity and hours, and compare keeping spike capacity running all month against adding it only for the on-sale window.

cost.py
# ILLUSTRATIVE prices in made-up units. Replace with your provider's price list.
HOURS_PER_MONTH = 730
PRICE = {
    "small_vm_hour": 0.02,
    "medium_vm_hour": 0.08,
    "db_hour": 0.15,
    "object_gb_month": 0.02,
    "egress_gb": 0.09,
}

def monthly(vms_small=0, vms_medium=0, dbs=0, stored_gb=0, egress_gb=0):
    return {
        "small VMs": vms_small * PRICE["small_vm_hour"] * HOURS_PER_MONTH,
        "medium VMs": vms_medium * PRICE["medium_vm_hour"] * HOURS_PER_MONTH,
        "database": dbs * PRICE["db_hour"] * HOURS_PER_MONTH,
        "object storage": stored_gb * PRICE["object_gb_month"],
        "data egress": egress_gb * PRICE["egress_gb"],
    }

normal = monthly(vms_small=2, dbs=1, stored_gb=200, egress_gb=500)
print("normal month (illustrative units)")
for item, cost in normal.items():
    print(f"  {item:15} {cost:9.2f}")
print(f"  {'total':15} {sum(normal.values()):9.2f}")

# Extra capacity for a 6-hour sale versus leaving it running all month
extra_per_hour = 4 * PRICE["medium_vm_hour"]
print()
print("4 extra medium VMs for a 6-hour sale :", round(extra_per_hour * 6, 2))
print("same 4 VMs left running all month    :", round(extra_per_hour * HOURS_PER_MONTH, 2))

Output

normal month (illustrative units)
  small VMs           29.20
  medium VMs           0.00
  database           109.50
  object storage       4.00
  data egress         45.00
  total              187.70

4 extra medium VMs for a 6-hour sale : 1.92
same 4 VMs left running all month    : 233.6

The lesson is not the numbers but the shape. In this made-up model the database dominates the everyday bill, and the spike capacity is nearly free if it exists only for six hours but more expensive than the whole rest of the system if it is left on. That is the economic case for elasticity: pay for peak capacity only while you need it. It also shows what to question next: could the database be a smaller size outside the on-sale window, and is the egress figure realistic once the CDN absorbs most image traffic?

Common mistakes

  • Treating object storage like a file system. Renaming a "folder" means copying every object, and appending to an object means rewriting it. Symptom: slow, expensive operations that would be instant on a disk.
  • Storing sessions or uploads on the app server. Symptom: users get logged out or lose uploaded files when a request lands on a different instance, or whenever you scale in.
  • Running a self-managed database on a VM "to save money". The cheaper hourly price ignores the engineer-hours for patching, backups and failover. Symptom: an untested restore procedure discovered during an outage.
  • Choosing serverless for steady heavy load without checking the bill. Symptom: a function invoked millions of times a day costing more than a small container would.
  • Sizing for the peak all month. Symptom: servers at five percent CPU nearly every day. Use autoscaling or scheduled scaling for known events such as an on-sale.

How this shows up in real projects and interviews

Interviewers ask "where would you store user-uploaded images?" (object storage with a database row pointing to it) and "when would you use serverless?" (spiky, event-driven, short-lived work). In real projects the best habit is to write a short architecture note, much like the diagram above, listing for each component why it is that type, what happens when it fails and roughly what it costs. Teams that do this catch the stateful-server and idle-capacity mistakes in review instead of in production.

Try it yourself

Adapt the ticket-booking architecture to a different product, such as a photo-printing shop or a bus-pass renewal portal. Draw a text diagram with at most eight boxes, and for each box name the compute or storage type and one sentence on why. Then edit cost.py to model your own components with prices you invent, and note which line dominates.

Show a hint

Ask of each box: is it steady or bursty, does it hold state, and what happens when it fails? Anything holding state belongs in a database or object storage, not on a server's disk.

Key takeaways

  • Match compute to workload shape: VMs for control, containers or platforms for steady web apps, functions for bursty event-driven work.
  • Object storage holds files, block storage backs a single machine's disk, file storage is a shared folder, and a database holds structured, consistent records.
  • Keep application servers stateless by moving files to object storage and records to a database.
  • Put slow, non-urgent work behind a queue so it cannot slow down the user-facing path.
  • Estimate costs early with rough numbers; elasticity makes short peaks cheap and always-on peak capacity expensive.

Test yourself

A trick from this lesson's ride: Files go in the bucket; the database keeps only a pointer to each one. Four more tricks like it wait along the route, each followed by a question.

Ride this lesson

Frequently asked questions

When should I use serverless instead of virtual machines?

Use serverless functions for short, event-driven or spiky workloads such as processing uploads, handling webhooks or scheduled jobs, where scaling to zero saves money and you want no server management. Prefer VMs or containers for long-running, steady, latency-sensitive services or software that needs full control of its environment.

What is the difference between object storage, block storage and file storage?

Object storage keeps whole files as objects addressed by key over HTTP and scales almost without limit, suited to media and backups. Block storage is a raw disk attached to one server, suited to databases and system disks. File storage is a shared network folder multiple servers can mount at once.

Why shouldn't I store files on my web server's disk in the cloud?

Servers in the cloud are replaced and scaled in and out freely, so local files can vanish, and other instances cannot see them. Keeping servers stateless, with uploads in object storage and data in a database, lets any instance serve any request and makes scaling and recovery simple.