Serverless vs VMs: when Cloud Run beats always-on instances

Most teams default to virtual machines because that’s what they’ve always run. But the “always-on” model has a cost you don’t see until you’re paying for machines that sit idle most of the day.

The two models

  • VMs (Compute Engine): you provision a machine, it runs 24/7, and you pay whether or not it’s busy. Predictable, but you size for peak and pay for idle.
  • Serverless (Cloud Run): you deploy a container, and the platform spins instances up and down with demand, scaling to zero when nothing’s happening.

When serverless wins

  • Bursty traffic: an API that’s quiet at night and spikes at lunch. Serverless scales to zero and back in seconds.
  • Event-driven work: webhooks, background jobs, scheduled tasks. Why keep a server awake for a job that runs once an hour?
  • Small teams: no patching, no capacity planning, no 2am pages about a full disk.

When VMs still make sense

  • Steady, high-utilization workloads: if a machine runs at 70%+ all day, you’re not wasting much, and reservations cut the rate.
  • Long-running processes: anything that holds a connection open for hours (some GPU inference, streaming) fits VMs better.
  • Specific hardware: certain GPUs, network shapes, or licensing constraints.

The cost story

Serverless looks “more expensive per second” on paper. But you only pay for the seconds you use. A workload that idles 20 hours a day can cost a fraction of its VM equivalent, in practice, we’ve seen migrations cut infrastructure spend by 62% by moving bursty services to Cloud Run while keeping steady-state jobs on reserved VMs.

How to decide

Ask three questions: Is the traffic bursty or steady? Is it event-driven or always-on? Does it need specific hardware? Answer those honestly and the right model usually picks itself.

Next: Why we migrate WordPress sites to Astro.

← Back to blog