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.