A Windows 11 VM in Proxmox VE was showing nearly 100% memory usage in monitoring.
Inside Windows Task Manager, however, actual memory usage was only around 30–50%.
At first glance, that looks like a monitoring problem.
It wasn't.
The issue was in the VM configuration: the PVE Ballooning Device had been disabled, which meant Proxmox VE was not receiving the guest memory statistics needed to reflect the actual Windows memory state.
I encountered this while monitoring a Proxmox VE environment with OpsHome NOC.
This post documents how I traced the discrepancy and fixed it.
The symptom
On the same Proxmox VE host, the memory usage of Ubuntu VMs looked normal.
One Windows 11 VM was different.
The VM had 24 GB of RAM configured, but the monitoring result remained close to:
Memory: 100%
Used: about 24.2 GB
Total: 24 GB
Inside Windows 11 Task Manager, however, the VM was clearly not using all of its memory.
The difference looked roughly like this:
Monitoring: 90%–100%
Windows 11: 30%–50%
That is too large a difference to treat as a normal sampling variation.
If you encounter something similar, especially when Linux VMs on the same Proxmox host look normal, do not immediately assume:
- Windows has a memory leak
- The monitoring threshold is wrong
- The monitoring application is calculating memory incorrectly
The more important question is:
Is Proxmox VE actually receiving the correct memory statistics from the Windows guest?
Checking BalloonService inside Windows 11
For Proxmox VE to obtain useful guest memory statistics from a Windows VM, the VirtIO Balloon driver and its related Windows service need to be available.
Inside Windows 11, I opened PowerShell and checked BalloonService:
Get-Service *balloon*
The result showed:
Running BalloonService
So the Windows-side BalloonService was already installed and running.
At this point, the guest-side service did not appear to be the problem.
The next step was to check the VM configuration on the Proxmox side.
Checking the Proxmox VE configuration
On the PVE host, I checked the VM memory configuration.
In this example, the VM ID is 100:
qm config 100 | grep -E '^(memory|balloon):'
The result was:
balloon: 0
memory: 24576
That was the key clue.
balloon: 0 means the Ballooning Device is disabled for the VM.
So the situation was effectively:
Windows 11
↓
VirtIO BalloonService running
↓
PVE Ballooning Device disabled
↓
Guest memory statistics path incomplete
↓
PVE memory information does not reflect
the actual Windows memory state
↓
Monitoring receives that upstream data
The monitoring software was not the root cause.
The VM configuration was incomplete.
Why this can be confusing
This issue is easy to misdiagnose because Windows itself can continue operating normally.
For example:
Windows boots normally
Applications work normally
Network works normally
Disk works normally
There may be no obvious guest OS failure.
The problem only becomes visible when you compare:
Windows Task Manager
vs.
Proxmox VE memory statistics
vs.
Monitoring data
That makes Ballooning configuration easy to overlook.
It is especially relevant for Windows VMs that have been migrated from another virtualization platform.
This VM had been migrated
VM migration is one situation where I would check Ballooning early.
When migrating a Windows VM from environments such as:
- VMware
- ESXi
- Hyper-V
- another Proxmox configuration
we usually spend most of our time checking:
CPU
VirtIO drivers
Disk controller
Network adapter
EFI
TPM
QEMU Guest Agent
Memory Ballooning may not get the same attention.
If Ballooning was disabled during migration or while tuning the VM, Windows can continue working normally while guest memory reporting becomes misleading.
Fixing the Ballooning configuration
In the Proxmox VE Web UI, open:
VM
→ Hardware
→ Memory
→ Edit
Then enable:
Ballooning Device
There is an important distinction here.
Enabling the Ballooning Device does not necessarily mean you have to let Proxmox dynamically reduce the amount of memory available to the Windows VM.
If you want the Windows 11 VM to continue using a fixed amount of RAM, you can set the maximum and minimum memory to the same value.
For this 24 GB VM, I used:
Memory: 24576 MiB
Minimum Memory: 24576 MiB
Ballooning Device: enabled
This preserves the fixed 24 GB memory allocation while enabling the Ballooning Device needed for the guest memory statistics path.
Command-line configuration
The same configuration can also be applied from the PVE command line.
For VM 100 with 24 GB RAM:
qm set 100 --balloon 24576
After changing the setting, verify it again:
qm config 100 | grep -E '^(memory|balloon):'
The important point is that it should no longer show:
balloon: 0
Fully shut down the Windows VM
After changing the Ballooning configuration, I fully shut down the Windows 11 VM and then started it again.
I did not rely only on an in-guest Windows restart.
The Ballooning Device is part of the VM's virtual hardware configuration, so a full stop and start is the safer approach.
The sequence was:
Shut down Windows 11
↓
Confirm the VM is stopped in PVE
↓
Start the VM again
Verifying Guest Memory Statistics
After Windows 11 started again, I first checked the VM configuration:
qm config 100 | grep -E '^(memory|balloon):'
Then I queried the current VM status through Proxmox VE:
pvesh get /nodes/PVE02/qemu/100/status/current \
--output-format json-pretty
Useful memory-related fields to look for include:
balloon
ballooninfo
free_mem
total_mem
The exact output may vary depending on your Proxmox VE version and VM configuration.
The important point is that guest memory information should now be available instead of the VM effectively being represented only by its allocated memory.
What changed after the fix?
Before fixing the Ballooning configuration, the situation looked approximately like this:
Windows 11 Task Manager: ~40%
Monitoring: ~100%
After restoring the Ballooning configuration and restarting the VM, the monitoring value gradually returned to a reasonable range:
Windows 11 Task Manager: ~40%
Monitoring: ~40%
The values do not have to match exactly every second or every percentage point.
Small differences are normal.
There are several reasons:
- Different sampling intervals
- Windows memory accounting
- Cached memory
- Available memory
- Timing differences between the guest and hypervisor
- Monitoring collection intervals
The important result is not exact percentage equality.
The important result is that the VM no longer remains incorrectly stuck near 100%.
Why Ubuntu VMs looked normal
One clue in this case was that Ubuntu VMs on the same Proxmox VE host were reporting reasonable memory usage.
Only the Windows 11 VM looked abnormal.
That suggested the problem was unlikely to be a global PVE monitoring failure.
Instead, it pointed toward something specific to the Windows VM or its guest-to-hypervisor statistics path.
That is why comparing multiple VMs on the same host can be useful during troubleshooting.
If you see:
Ubuntu VM: normal
Ubuntu VM: normal
Windows 11 VM: nearly 100%
while Task Manager shows much lower usage, checking the Windows Ballooning configuration is a good next step.
When should you check Ballooning first?
I would check Ballooning relatively early when several of these conditions are present:
- A Windows VM stays at 90–100% memory usage.
- Windows Task Manager shows substantially lower memory usage.
- Linux VMs on the same PVE host look normal.
- The Windows VM was migrated from VMware, ESXi, Hyper-V or another platform.
- VM memory settings were manually adjusted.
- Ballooning was intentionally disabled to keep memory fixed.
- BalloonService is installed and running inside Windows.
- QEMU Guest Agent is working, but memory statistics still look unreasonable.
A configuration such as this deserves particular attention:
balloon: 0
memory: 24576
especially when it appears together with a large difference between Windows Task Manager and PVE-based monitoring.
QEMU Guest Agent is not the same thing as BalloonService
Another useful distinction is that QEMU Guest Agent and the VirtIO Balloon driver are related to guest integration, but they are not the same component.
It is possible to have:
QEMU Guest Agent: working
BalloonService: running
Ballooning Device: disabled
and still have misleading memory statistics.
So when troubleshooting this issue, checking only QEMU Guest Agent is not enough.
The Ballooning configuration itself also needs to be verified.
Fixed memory and Ballooning are not mutually exclusive
One reason people disable Ballooning is that they want the VM to always have a fixed amount of memory.
That requirement is reasonable.
But disabling the Ballooning Device entirely can also affect the guest memory statistics path.
For a VM that should always remain at 24 GB, a more useful configuration is:
Maximum Memory: 24576 MiB
Minimum Memory: 24576 MiB
Ballooning Device: enabled
Conceptually:
Minimum = Maximum
means Proxmox does not have a lower memory target to reclaim toward.
At the same time, the Ballooning Device remains present for the Windows guest integration path.
The complete troubleshooting chain
The final troubleshooting process was:
Windows 11 shows normal memory usage
↓
Monitoring shows nearly 100%
↓
Compare other VMs on the same PVE host
↓
Ubuntu VM memory looks normal
↓
Check Windows BalloonService
↓
BalloonService is running
↓
Check PVE VM configuration
↓
Find balloon: 0
↓
Enable Ballooning Device
↓
Set minimum memory = maximum memory
↓
Fully stop and start Windows 11
↓
Check PVE Guest Memory Statistics
↓
Observe monitoring again
The monitoring software was not the root cause
This is the main lesson from the troubleshooting case.
OpsHome NOC was displaying the memory information available through the Proxmox VE monitoring path.
The root cause existed upstream.
The actual chain was:
PVE Ballooning Device disabled
↓
Guest Memory Statistics incomplete
↓
PVE memory information differs from
the actual Windows memory state
↓
Monitoring receives the PVE data
↓
Windows VM appears close to 100%
So when monitoring information clearly conflicts with what you see inside a guest operating system, it is worth checking the entire data path before concluding that the monitoring application is calculating incorrectly.
For a virtualized workload, that path looks roughly like:
Guest OS
↓
Guest drivers and services
↓
Hypervisor
↓
Hypervisor API / statistics
↓
Monitoring
Every downstream layer depends on the quality of the data provided by the layer before it.
Final checklist
If a Windows 11 VM appears to use nearly 100% memory in Proxmox VE monitoring while Task Manager says otherwise, try this checklist:
1. Check Windows Task Manager
↓
2. Confirm the actual guest memory usage
↓
3. Check BalloonService in Windows
↓
4. Run:
qm config <VMID>
↓
5. Look for balloon: 0
↓
6. Enable the Ballooning Device
↓
7. If fixed RAM is required,
set minimum memory = maximum memory
↓
8. Fully shut down the VM
↓
9. Start the VM again
↓
10. Verify Guest Memory Statistics in PVE
↓
11. Observe the monitoring data again
For example:
Get-Service *balloon*
Then on Proxmox VE:
qm config 100 | grep -E '^(memory|balloon):'
And after fixing the configuration:
pvesh get /nodes/PVE02/qemu/100/status/current \
--output-format json-pretty
Conclusion
In this case, the Windows 11 VM was not actually consuming all 24 GB of its memory.
The near-100% value was the result of an incomplete memory statistics path between the Windows guest and Proxmox VE.
The key configuration was:
balloon: 0
After enabling the Ballooning Device, keeping minimum and maximum memory equal, fully stopping and starting the Windows VM, and verifying the guest memory statistics, the reported memory usage returned to a reasonable range.
The main takeaway is simple:
Before blaming the monitoring layer, verify that the hypervisor is receiving the data you expect from the guest.
This is especially worth remembering after migrating Windows virtual machines between hypervisors.
This troubleshooting case was originally documented while monitoring a Proxmox VE environment with OpsHome NOC.
Original article:
https://docs.opshome.run/articles/opshome-noc-pve-windows-ballooning-memory-monitoring.html
Top comments (0)