Direct answer: When a Windows server is short of memory and no process explains it, measure before naming a cause. Microsoft's first step is Performance Monitor: record Memory\Pool Nonpaged Bytes, Memory\Pool Paged Bytes and Paging File\% Usage over several hours. Only if pool keeps growing with a steady workload do you look for the pool tag that grows (PoolMon) and map it to a candidate driver; a handle count that keeps rising for one process is supporting evidence of the same kind of fault. A tag or count that rises is a lead, not proof: confirm it is not freed when the workload ends, then take it to the vendor. A restart clears the symptom for a time; it fixes nothing.
Why it matters
The quick check, sorting processes by memory, finds nothing, and the reactions are to add RAM or schedule a restart. Either can be a reasonable stopgap, but neither identifies the component. Without measurements the same failure comes back and nobody can tell the vendor what to fix.
How it works
Measure first
Microsoft's leak guide says: "Start by checking if a leak exists using Performance Monitor, then follow the appropriate troubleshooting path." Its PerfMon procedure adds three counters, Memory > Pool Nonpaged Bytes, Memory > Pool Paged Bytes and Paging File > % Usage, sampled every 600 seconds. It warns that values change rapidly at first and "It can take time for the memory pools values to reach a steady state. Wait several hours before you decide there's a leak." Microsoft also states: "Kernel-mode memory leaks usually deplete nonpaged pool."
Growth in these counters is not by itself a leak. A heavier workload, a new role or a component that caches more will also raise them. Record what the server was doing during the measurement.
Pool memory
Microsoft's leak article: "A memory leak occurs when a process allocates memory from the paged or nonpaged pools but doesn't free it. As memory is depleted over time, Windows slows down and may experience system failures." Pool is kernel memory used by Windows components and drivers, and it does not appear as any one process's working set, so a process list does not show it.
Pool tags
Each pool allocation carries a four-character tag chosen by the driver or component that made it. Microsoft states that on Windows Server 2003 and later, pool tagging is always enabled. PoolMon "displays data that the operating system collects about memory allocations from the system paged and nonpaged kernel pools, and the memory pools used for Terminal Services sessions", grouped by tag.
Microsoft's method follows from this. If you do not know which driver is responsible, use PoolMon first: "This technique reveals the pool tag associated with the memory leak; the driver or component that uses this pool tag is responsible for the leak." A tag found this way names a candidate owner; it still needs confirmation from the vendor or the code before anything is removed.
Reading PoolMon
PoolMon's header shows paged and nonpaged pool totals. Each row is a tag with its pool type, allocation and free counts, Diff (allocations minus frees) and Bytes. Microsoft's PoolMon examples watch those two columns over time: "examine the Diff ... and Bytes ... values for each tag, and note any that continually increase." The reasoning, from Microsoft's PoolMon leak procedure: once a workload is steady it allocates and frees at the same rate; if it allocates faster than it frees, its memory use grows over time, which Microsoft treats as an indication of a leak, not proof. A changing workload or a component that legitimately caches more can also raise a tag.
The /g parameter adds a Mapped_Driver column from pooltag.txt, which names the component for common tags. Microsoft notes that pooltag.txt "is not a complete list of all tags used in Windows"; an unlisted tag shows as "Unknown driver".
Session pools on Remote Desktop hosts
PoolMon's /s parameter displays the Terminal Services session pools. Microsoft's example 4 investigates a suspected printer driver: some printer drivers use the Drsd tag for GDI objects, and if such a driver leaks objects, the memory with that tag leaks too.
Handles
A handle is a process's reference to a kernel object such as a file, registry key, event, thread or process. Microsoft's Kernel Objects page states: "When an application closes the last handle to a kernel object, the system removes the object from memory," and a handle "remains valid until the application closes the handle or terminates." A process that keeps opening handles without closing them therefore keeps objects alive. Sysinternals Handle "displays information about open handles for any process in the system" and, with -s, prints a count of each handle type. A rising handle count is supporting evidence; it is not a byte measure of leaked kernel memory, and the fetched sources give no per-process handle counter for Performance Monitor.
Physical memory view
Sysinternals RAMMap shows how Windows assigns physical memory, including "how much RAM is used by the kernel and device drivers". Its Use Counts tab gives a usage summary by type, and it can save and load snapshots for comparing two points in time.
Read-only checks
None of these were run for this article. Performance Monitor is part of Windows. PoolMon ships in the Windows Driver Kit, and Handle and RAMMap are separate downloads; installing any of them on a production server is a change, outside read-only diagnosis, and needs its own approval. A test copy that shows the same growth is the alternative.
- Trend. In Performance Monitor, record Pool Nonpaged Bytes, Pool Paged Bytes and Paging File % Usage every 600 seconds for several hours, with notes of the workload in that period.
- Where the memory is. In RAMMap's Use Counts tab, record the summary by type, save a snapshot and compare with a later one.
- Which pool tag:
poolmon /p /p /bMicrosoft's example 3: paged pool only, sorted by bytes. "Starting PoolMon changes the data", so let it settle; record the screen, switch withp, and repeat at intervals over hours. Note tags whose Diff and Bytes keep rising. - Candidate driver:
poolmon /iTAG /g "<path>\pooltag.txt"Tags are case-sensitive. Microsoft notespooltag.txt"is not a complete list of all tags used in Windows"; an unlisted tag shows as "Unknown driver". - Freed or not. Microsoft's PoolMon leak procedure says: "Stop your test and wait a few hours. Determine how much of the tag was freed up in this time." On a production server, use a workload that has finished on its own or an already authorised test workload. Stopping a production service for this is a separate, disruptive change; keep the measurement running across it so the baseline is not lost.
- Handles:
handle -s -p <process>Repeat over time for a process whose handle count rises; note which type grows. Handle needs administrative privilege.
Candidate causes (hypotheses to test)
| Candidate | Evidence | Next decision |
|---|---|---|
| Not a leak: workload or cache growth | Growth matches workload; bytes freed when it ends | Capacity decision; record the normal peak |
| Driver leaking nonpaged pool | Pool Nonpaged Bytes rises at steady workload; one tag's Bytes and Diff rise | Vendor confirmation, then update |
| Driver leaking paged pool | Pool Paged Bytes rises; one paged tag rises | Vendor confirmation, then update |
| Printer driver objects on a Remote Desktop host | Session pool tag such as Drsd rising (/s) |
Printer driver vendor |
| Process leaking handles | Handle count and one type rising for one process | Application vendor |
| Unknown tag | "Unknown driver" in Mapped_Driver |
Vendor or Microsoft support |
Decision guidance
Every item below is a change and needs a change record. None were executed for this article.
| Decision | Prerequisites | Reference |
|---|---|---|
| Install PoolMon, Handle or RAMMap | Approval for the server, or a test copy | WDK; Sysinternals pages |
| Add memory as a capacity stopgap | Measurements recorded; documented as interim, not a leak fix | Editorial |
| Scheduled restart as a stopgap | Growth rate recorded; documented as interim | Editorial |
| Update the driver or application | Vendor confirms the tag or handle growth belongs to it | Vendor release notes |
| Remove or disable the component | Vendor confirmation; dependencies checked; maintenance window | Vendor guidance |
| Kernel debugger or Driver Verifier | Test system or vendor engagement only | Microsoft debugger documentation |
What not to do
- Do not close handles in another process with
handle -c. Sysinternals warns: "Closing handles can cause application or system instability." - Do not present a restart or more RAM as the fix.
- Do not remove a driver on the strength of a
pooltag.txtmapping alone. - Do not use the kernel debugger or Driver Verifier on a production server.
- Do not stop production services to "test" a leak without its own approval.
Limitations
- Untested: no tool was run in a lab.
- Commit charge, Task Manager pool display, resource exhaustion events and memory dumps are not covered; no fetched page gives commit counters.
- No per-process handle counter for Performance Monitor was sourced.
- User-mode heap leaks inside a process are a separate path Microsoft links to and are not covered.
- PoolMon, Handle and RAMMap compatibility with current Windows Server releases was not validated beyond their pages.
Acceptance checklist
- [ ] Counter trends over several hours are recorded with workload notes.
- [ ] Any growing pool tag or handle type and process are named, with the mapping marked as candidate until the vendor confirms.
- [ ] Bytes not freed after a finished or authorised test workload are recorded.
- [ ] Any stopgap (memory, restart) is recorded as interim, with its reason.
- [ ] After a vendor fix, the same counters stay flat over a comparable period with a comparable workload.
Sources
Displayed dates as shown when accessed on 30 October 2026.
- Microsoft Learn, Find and Fix Memory Leaks in Windows. 2025-11-07.
- Microsoft Learn, Look For Potential Memory Leaks With PerfMon. 2025-07-23.
- Microsoft Learn, Finding a Kernel-Mode Memory Leak. 2021-12-15.
- Microsoft Learn, Use PoolMon to Find a Kernel-Mode Memory Leak. 2025-07-23.
- Microsoft Learn, PoolMon. 2025-07-23.
- Microsoft Learn, PoolMon Examples. 2023-05-18.
- Microsoft Learn, Using the Kernel Debugger to Find a Kernel-Mode Memory Leak. 2021-12-15.
- Microsoft Learn, Kernel Objects. 2021-01-07.
- Microsoft Sysinternals, Handle. 2022-10-26.
- Microsoft Sysinternals, RAMMap. 2026-03-26.
Related articles
- Print Spooler crashes on Remote Desktop hosts: suspected driver faults, isolation and Point and Print
- Linux OOM killer on a VM: read the kernel log, find the cause and set limits deliberately
- Windows cumulative update fails to install: component store diagnosis and repair decisions with DISM and SFC
Learning notes
- Measure pool and page file counters over hours before naming a cause.
- A growing pool tag points to a candidate driver; the vendor confirms it.
- Handle growth supports the picture; it is not a byte count of kernel memory.
- "Freed or not" is tested with a finished or authorised workload, not a production stop.
- Restarts and added memory are stopgaps, recorded as such.