Introduction
You open the Proxmox VE web interface, glance at the Summary tab, and the CPU usage graph is pinned near the top of the chart. Maybe a VM feels sluggish. Maybe the host fan just kicked into high gear for no obvious reason. Either way, you're now staring at a number that's too high and no clear explanation for why.
The good news is that high CPU usage on a Proxmox host almost always traces back to one of a handful of causes, and most of them are easy to check once you know where to look. This guide walks through how to actually find out what's eating your CPU, not just how to make the graph look better.
We're using Proxmox VE 9.x for the commands and menu paths below. Everything here also applies to 8.x hosts — the tools involved (top, qm, iotop) haven't changed in any way that matters for this guide.
What You Will Learn
- How to read the CPU graphs in the Proxmox web interface correctly, including the difference between usage and I/O delay
- How to identify which specific VM or container is responsible for the load
- The most common real-world causes: backup jobs, CPU type mismatches, IO wait disguised as CPU load, and runaway guest processes
- How to set per-VM CPU limits so one guest can't starve the others
- What normal CPU usage actually looks like on an idle host, so you stop chasing ghosts
- How to tell the difference between a host problem and a problem inside one guest
What Is This Feature?
There isn't a single "CPU usage" feature to enable here — this guide is about reading the tools Proxmox already gives you and knowing what they're actually measuring.
The CPU graph on a node's Summary page reports usage for the whole physical host, combining every VM, every LXC container, and Proxmox's own background services (the web UI, the cluster stack, backup jobs, and so on). A VM's own Summary tab shows something different: how much of its allotted vCPU time that one guest is using, not the host as a whole. Mixing these two up is the single most common reason people think something is broken when it isn't.
There's also a number hiding inside that CPU percentage that trips up almost everyone the first time: iowait. This is time the CPU spent doing nothing because it was waiting on a slow disk, not time it spent actually computing anything. A host can show 80% CPU usage that's really 75% iowait and 5% real work — and the fix for that has nothing to do with CPU limits at all.
One more term worth knowing before you go further: KVM, the Linux kernel technology Proxmox uses to run virtual machines. Every running VM shows up on the host as its own KVM process, visible in a normal process list like any other program. That's what makes tracking down a noisy VM straightforward — you're really just hunting for one Linux process among many.
Why Would You Use It?
Chasing high CPU usage matters for a few concrete reasons, not just tidiness.
If the host itself is maxed out, every VM on it slows down at once, even ones that aren't doing anything demanding. That's the scenario where a Home Assistant instance starts lagging because a completely unrelated Windows VM is compiling something in the background.
It also matters for hardware longevity and noise. A host that's constantly pegged runs hotter, and on smaller homelab boxes that usually means the fans spinning up loud enough to notice from the next room. I've had more than one "why is my server so loud" question turn out to be a stuck backup job hammering CPU at 3 AM.
And sometimes what looks like a CPU problem is actually a storage problem wearing a CPU costume — high iowait pinning the usage graph while the actual disks are the real bottleneck. Diagnosing correctly here saves you from throwing a CPU upgrade at a problem that a faster SSD would have fixed for a third of the price.
Prerequisites
- Root or SSH access to your Proxmox VE host (Datacenter → Node → Shell also works if you'd rather stay in the browser)
- At least one running VM or container, so there's something to actually investigate
- Ten to fifteen minutes — most of this is watching numbers change in real time, not editing config files
You don't need any monitoring stack set up for this. Everything below works with tools that ship on every Proxmox VE install by default.
Step-by-Step Tutorial
Step 1: Confirm it's actually the host, not one VM reporting its own load
Open the Proxmox web interface, click Datacenter, then click your node's name in the left tree, and look at the Summary tab's CPU graph. This number covers everything running on that physical machine.
Now click into a specific VM and check its own Summary tab. If the VM shows 100% CPU but the host shows 20%, the problem is scoped to that one guest — probably something running inside it, not a host-wide issue. If the host itself is pinned high, keep going.
Step 2: Log into the host shell and run top
SSH into the Proxmox host (or use the node's Shell button in the web UI) and run:
top
This opens a live, auto-refreshing list of every process on the host, sorted by CPU usage. The first few lines at the top of the screen are worth reading before you even look at the process list — specifically the %Cpu(s) line, which breaks usage down into categories like us (user processes), sy (system/kernel), and the one that matters most here: wa, which is iowait.
If wa is sitting at 20% or higher while everything else looks modest, your CPU isn't actually the bottleneck — your storage is, and the CPU is just idling while it waits. Skip ahead to the iowait section below.
If instead you see one or more processes named kvm near the top of the list eating real CPU (high in the us column, not wa), you've found your VM. Press q to exit top once you've noted the process ID (PID) in the leftmost column.
Step 3: Match that KVM process back to a specific VM
A raw PID doesn't tell you which VM it belongs to. Get the mapping with:
qm list
This lists every VM's ID, name, and status, but not the PID directly. To go the other direction — PID to VM — run:
ps -p <PID> -o pid,cmd
and look at the full command line. It'll include -id <VMID> somewhere in the output, which you can match against the VM list from the previous command. Once you know the VMID, open that VM in the web interface and check what's actually running inside it — a stuck process, a runaway cron job, or a workload that's simply bigger than the vCPUs you gave it.
Step 4: Rule out a backup job in progress
Backups are one of the most common causes of a sudden CPU spike, and they're easy to miss because they run on a schedule you might not remember setting. Check Datacenter → Backup for a job currently running, or look at the task log at the bottom of the web interface for an active vzdump task.
Compression is usually the culprit here specifically — zstd compression, while fast, still uses real CPU time, and a backup job covering several large VMs at once can noticeably load a modest homelab CPU for the duration of the job. This is expected behavior, not a bug, but it explains a lot of "why is my server slow right now" moments that happen to line up with 2 or 3 AM.
Step 5: Check for a CPU type mismatch
Every VM has a configured CPU type, set under the VM's Hardware tab or with qm config <VMID>. The default in many setups is kvm64, a very conservative, generic CPU profile designed for maximum compatibility across different physical hosts — including ones you might migrate the VM to later.
The tradeoff is that kvm64 doesn't expose newer CPU instructions to the guest, which means some workloads inside the VM end up doing more work in software emulation than they would with a more modern CPU type. Switching the CPU type to host (which passes through your exact physical CPU's flags) or to a modern baseline like x86-64-v2-AES can noticeably cut CPU usage for compute-heavy guests, at the cost of losing the ability to live-migrate that VM to hardware with a different CPU vendor or generation.
For a single-node homelab where you're never migrating between different physical CPUs, setting CPU type to host is usually a safe, worthwhile change.
Step 6: Set a CPU limit so one VM can't starve the others
If a specific VM is legitimately doing heavy work and you don't want it dragging every other guest down with it, set a hard limit. In the VM's Hardware tab, edit the CPU settings, or from the command line:
qm set 100 --cpulimit 2
This caps VM 100 to the equivalent of 2 full CPU cores of host time, regardless of how many vCPUs you've assigned it or how hard it tries to use them. It's a hard ceiling, not a suggestion — useful for a VM you know is a resource hog but still want to keep online.
Commands Explained
top— a live, continuously refreshing view of every process on the host and how much CPU and memory each one is using. Pressqto quit.qm list— lists every VM on the host along with its ID, name, and current status (running, stopped, and so on).qm config <VMID>— prints a VM's full configuration, including its CPU type, memory allocation, and disk setup.ps -p <PID> -o pid,cmd— shows the full command line a specific process was started with, which is how you trace a generickvmprocess back to a VM ID.qm set <VMID> --cpulimit <N>— caps a VM to at most N full cores' worth of host CPU time, as a hard limit.qm set <VMID> --cpuunits <N>— sets a VM's relative CPU priority compared to other VMs when the host is fully loaded and guests are competing for time. Higher numbers win more of the contested CPU time; it does nothing when the host isn't under contention.
Common Errors
Host CPU graph shows high usage but every individual VM looks idle. This is almost always iowait, Proxmox's own background services, or a backup job — not a guest. Re-check the %Cpu(s) breakdown in top for the wa value before assuming a VM is to blame.
A VM's own CPU usage graph reads 100% constantly, even when nothing seems to be running inside it. Check whether the CPU type is set correctly and whether the guest OS itself has a stuck process — Windows VMs in particular can pin a core at 100% due to unfinished Windows Update tasks or a driver that never installed correctly, which is unrelated to Proxmox itself.
CPU usage spikes every night at the same time. Almost always a scheduled backup job. Check Datacenter → Backup for the job's schedule and consider staggering start times if you run several large VMs so they don't all compress at once.
"cpulimit" doesn't seem to do anything. Double check you set it on the correct VMID with qm config <VMID>, and remember it's a hard ceiling on host CPU time, not a vCPU count — a VM with 4 vCPUs and cpulimit 1 can still show all 4 vCPUs "active" inside the guest, just each getting a much smaller slice of real time.
Troubleshooting
If iowait is the real story, the next question is which disk or which VM is generating it. Run iotop (install it first with apt install iotop if it isn't already present) to see per-process disk activity, the same way top shows per-process CPU activity. A single VM doing heavy database writes on slow spinning storage is a very common source of iowait that gets misread as a CPU problem.
If you're on ZFS storage, keep in mind that a scrub (ZFS's built-in data integrity check) or a resilver after replacing a disk will both generate real, sustained load — that's expected and temporary, not a sign of misconfiguration. Check zpool status to see if either is currently running before you go looking anywhere else.
If usage looks high across the board with no single obvious culprit, check Datacenter → Backup and Datacenter → Replication for overlapping scheduled jobs. It's easy to end up with a backup job and a ZFS replication job scheduled at the same hour without realizing it, and the combined load looks much worse than either job alone.
Finally, don't rule out the obvious: check that no VM was accidentally given more vCPUs than the host physically has cores. Proxmox will let you over-allocate vCPUs across VMs (this is normal and usually fine, since guests rarely all peak at once), but a single VM configured with more vCPUs than exist on the host can behave strangely under load.
Best Practices
- Set
cpulimiton any VM you know is a heavy, bursty workload, so a runaway process inside it can't take the whole host down with it. - Use CPU type
hoston single-node setups where you'll never migrate to different hardware — it's close to free performance you're otherwise leaving on the table. - Stagger backup and replication schedules across different hours instead of running everything at midnight by default.
- Get familiar with what your host's idle baseline actually looks like in
topbefore something goes wrong, so you can immediately recognize when a number is genuinely abnormal instead of guessing. - Reach for
iotopbefore you reach for a CPU upgrade — a surprising number of "CPU problems" on Proxmox are storage problems in disguise.
Frequently Asked Questions
Is it normal for Proxmox to use some CPU even with no VMs running?
Yes. The web interface, cluster services, and periodic status checks all use a small, steady amount of CPU on their own. A few percent at idle is normal; anything sustained above roughly 10-15% with no VMs running is worth investigating.
Does more vCPUs always mean better performance?
No. Assigning more vCPUs than a workload can actually use just adds scheduling overhead without any benefit, and can occasionally make things slower. Match vCPU counts to what the guest workload genuinely needs.
Why does my Windows VM use more CPU than an equivalent Linux VM?
Windows tends to run more background services by default, and without the VirtIO drivers installed it also falls back to slower emulated hardware, which increases CPU overhead. Installing the VirtIO drivers usually closes a meaningful chunk of that gap.
Can I limit CPU usage for LXC containers the same way?
Yes. Containers support the same cpulimit and cpuunits options as VMs, set from the container's Resources tab or with pct set <CTID> --cpulimit <N>.
Will disabling CPU security mitigations fix high usage?
It can reduce overhead slightly on some workloads, but it also removes protection against real, documented CPU-level vulnerabilities. It's not a recommended first step, and most CPU issues on a homelab host have a safer, more direct fix further up this guide.
Conclusion
High CPU usage on Proxmox is rarely mysterious once you separate host-wide load from a single VM's own graph, and once you know to check iowait before blaming the CPU outright. Most of the time it's one of four things: a backup running, a CPU type that's forcing more emulation than necessary, a guest process that's simply stuck, or storage that can't keep up.
Work through the steps in order — top, then qm list, then a look at scheduled jobs — and you'll usually land on the actual cause within a few minutes instead of guessing at hardware upgrades you don't need yet.