Virtual machines (VMs, programs that emulate an entire physical computer inside your existing one) have been declared dead at least once a year for the last decade. Containers were supposed to make them obsolete. Then serverless was supposed to. Then WebAssembly. Each wave has been real, but VMs keep showing up in places you’d expect them to have disappeared from. After spending the last several months working with a mix of VMs, containers, and bare metal, I want to lay out the cases where VMs are still the right tool, and a few where they aren’t.
The case nobody is making for VMs in 2026
The story you usually hear is the opposite: VMs are legacy, they’re slow, they waste resources. That story is partly true and partly the kind of binary thinking that ages badly. A VM running on a modern Linux kernel with KVM (Kernel-based Virtual Machine, Linux’s built-in hypervisor) is fast enough that, in most benchmarks I’ve run, the overhead is in the single digits. For a lot of workloads, that gap has closed to the point where it doesn’t matter.
What VMs give you that containers and serverless don’t is a clean hardware boundary. The guest kernel is the guest kernel. If you’re running untrusted code, doing malware analysis, hosting customers with conflicting requirements, or building a multi-tenant platform, that boundary is what you actually want. Containers share the host kernel, which is great for density and bad for isolation when things go wrong.
Here’s the thing nobody’s talking about: the same Linux ecosystem that made containers a default is what made VMs competitive again. KVM got better. QEMU got better. The virtio (a standardized interface for virtualized disks, network, and other devices) driver stack matured. We stopped paying the I/O penalty we used to pay, and the only thing left to argue about is memory.
Isolation you can actually trust
When you put two customers on the same host with containers, the blast radius of a kernel exploit includes both customers. That’s a known, well-studied risk, and the mitigations (gVisor, seccomp profiles, rootless containers) work. They are not the same thing as a separate kernel, though, and a hard VM boundary is the simplest way to take that whole class of bug off the table.
This is why most cloud providers still default to VMs for customer-facing compute, even when they offer container products on the same hardware. The VM is the unit of tenancy. If you want to give a customer a “machine” and bill them by the hour, a VM is closer to what they expect than a container that could be moved to a different node between two requests.
There are also the obvious regulatory and audit cases. PCI-DSS (the Payment Card Industry Data Security Standard), HIPAA, and a few European data protection regimes treat a separate kernel as a meaningful boundary, and an auditor will accept it faster than they’ll accept a defense based on Linux capabilities and seccomp filters. The trade-off is that you pay for the isolation in resource overhead, but in some industries that cost is just the cost of doing business.
Workloads that need a real OS
Not every workload fits the container model. Windows workloads don’t run in a Linux container. Some legacy applications need a specific kernel version, a specific set of drivers, or a particular init system (the first process a Linux system runs at boot, traditionally SysVinit or systemd) that doesn’t translate cleanly. Some scientific software expects a real /dev tree, real block devices, and permissions that containers flatten.
A VM gives you a complete operating system to do what you want in. That includes rebooting. If you’ve ever tried to recover a broken container host by rebooting a node, you know that the container abstraction hides the kernel entirely. With a VM, you can reboot the guest, install kernel updates without touching the host, run a different distro, or run a different kernel version on the same physical hardware. For some teams that’s freedom, not legacy.
The flip side is that all that freedom costs you in startup time, image size, and resource overhead. A container can be up in a second. A VM takes ten to thirty seconds minimum, and a Windows VM can take minutes. If your workload is short-lived and you spin up a thousand of them, the math doesn’t favor VMs.
A stable abstraction for migration
One of the underappreciated reasons to keep VMs around is migration. vMotion (VMware’s live migration feature for moving a running VM between hosts with no downtime), live migration in KVM, and the equivalent features in Hyper-V exist because VMs are a portable, well-defined artifact. A VM image is a self-contained thing that can be moved, cloned, backed up, or restored without needing to understand the application inside it.
That property is what lets you move workloads between data centers, between cloud providers, or between on-prem and cloud without rewriting the application. Containers can do this too, in theory, but in practice most container images are tightly coupled to a specific base image, runtime, and orchestration system. Lift-and-shift is a much smaller project when the unit being moved is a VM.
This is also why disaster recovery vendors still sell VM-centric products. The snapshot-and-replicate model is older, simpler, and more battle-tested than the equivalent container ecosystem. It’s not glamorous, but it works.
Development environments that match production
A surprising number of teams I work with still ship VMs as dev environments, for one reason: production parity. If production runs on a specific Linux distribution with a specific kernel and a specific set of system services, the cheapest way to make a developer laptop match it is usually a VM. Vagrant (a tool that defines and provisions reproducible development environments) was built for this, and Multipass and Lima exist for the same reason.
The container-based alternative (Dev Containers, or running a full container with a fake init and fake systemd) is fine for many cases, but it breaks the moment the developer needs to test something that touches the kernel, the network stack in a way containers don’t expose, or filesystems that don’t compose well with overlay filesystems (the layered filesystem containers use to stack image layers). At that point, a VM is faster than fighting the abstraction.
Trade-offs
VMs are not a free lunch, and there are real cases where they are the wrong tool:
- Memory overhead is real. Every guest kernel and the related system services consume RAM that a container would not. On a small host, this matters.
- Boot time is measured in seconds, not milliseconds. If you need to scale to thousands of short-lived units, the math doesn’t work.
- Disk image sizes are large. A 20 GB Linux VM image is normal; a 20 GB container image is a smell. Storage and bandwidth costs add up.
- Nested virtualization (running a VM inside a VM) works, but slowly, and not all cloud providers let you do it. If you need a Kubernetes-in-a-VM-for-testing setup, you may find it harder than you expected.
- The tooling is less unified than the container ecosystem. Docker Compose has dozens of competitors, and most of them are about as good. The VM world is more fragmented.
When to use a VM and when not to
Use a VM when the workload needs a real OS, real isolation, or a portable artifact that doesn’t depend on a specific container runtime. Use a container when you want density, fast startup, and a workload that is comfortable sharing a kernel. Use both on the same host when different parts of the system have different needs, which is most of the time.
The right answer in 2026 is rarely “all VMs” or “all containers.” It’s “what boundary does this workload actually need, and which abstraction gives me that boundary with the least overhead.” For a lot of workloads, that answer is still a VM, and pretending otherwise usually means someone is going to learn a hard lesson the next time there’s a kernel vulnerability.