Exchange ServerTroubleshooting

High CPU or memory on Exchange Server: what's normal and how to find the real cause

Store processes holding most of the RAM is by design; sustained high CPU isn't. Map the busy process to its cause - search, IIS app pools, transport - and capture evidence with ExPerfWiz.

Task Manager on a busy Exchange server can look alarming: store processes holding tens of gigabytes, a row of w3wp.exe instances and noderunner.exe near the top of the CPU column. Some of that is by design and some is a symptom. In this post I'll separate the two on Exchange Server SE and Exchange 2019, then show a repeatable way to find what's really loading the server and prove the fix.

Errors this guide fixes

  • Windows successfully diagnosed a low virtual memory condition. The following programs consumed the most virtual memory:System log (Event ID 2004)
  • 452 4.3.1 Insufficient system resourcesNDR / queue LastError+3 more guides
  • Event ID 2004 (Resource-Exhaustion-Detector)System log
How this guide is organised: Symptoms → Why it happens → How to fix it → Verify the fix → Prevent it next timeFlow diagram of the article's sections in reading order: 1. Symptoms. 2. Why it happens. 3. How to fix it (4 steps: Rule out configuration first; Identify the process and what it serves; Act on the cause; Capture evidence for intermittent spikes). 4. Verify the fix. 5. Prevent it next time. Toolbox: Event ID 2004, w3wp.exe, noderunner.exe, Microsoft.Exchange.Store.Worker.exe, MSExchangeMapiMailboxAppPool.1Symptoms2Why it happens3How to fix it4Verify the fix5Prevent it nexttime1Rule out configurationfirst2Identify the process andwhat it serves3Act on the cause4Capture evidence forintermittent spikesTOOLBOXEvent ID 2004w3wp.exenoderunner.exeMicrosoft.Exchange.Store.Worker.e…MSExchangeMapiMailboxAppPoolHow this guide is organised: Symptoms → Why it happens → How to fix it → Verify the fix → Prevent it next timeFlow diagram of the article's sections in reading order: 1. Symptoms. 2. Why it happens. 3. How to fix it (4 steps: Rule out configuration first; Identify the process and what it serves; Act on the cause; Capture evidence for intermittent spikes). 4. Verify the fix. 5. Prevent it next time. Toolbox: Event ID 2004, w3wp.exe, noderunner.exe, Microsoft.Exchange.Store.Worker.exe, MSExchangeMapiMailboxAppPool.1Symptoms2Why it happens3How to fix it1Rule out configuration first2Identify the process and what it serves3Act on the cause4Capture evidence for intermittent spikes4Verify the fix5Prevent it next timeTOOLBOXEvent ID 2004w3wp.exenoderunner.exeMicrosoft.Exchange.Store.Worker.exeMSExchangeMapiMailboxAppPool
At a glance: how this guide is organised · 4 fix steps · 5 key tools

Symptoms#

  • Memory use sits close to the installed total, with Microsoft.Exchange.Store.Worker.exe processes at the top.
  • CPU stays high for long periods, led by noderunner.exe, w3wp.exe, EdgeTransport.exe or MSExchangeHMWorker.exe.
  • Outlook and Outlook on the web feel slow, queues build up, and sending servers receive 452 4.3.1 Insufficient system resources once transport back pressure starts.
  • The System log shows Event ID 2004 (Resource-Exhaustion-Detector):
Text
Windows successfully diagnosed a low virtual memory condition. The following programs consumed the most virtual memory: ...

Why it happens: normal versus not#

ProcessWhat it isNormalInvestigate when
Microsoft.Exchange.Store.Worker.exeOne per database copy; holds the database cacheLarge, steady memory use; Exchange 2019 and SE shift cache towards active copies (Dynamic Database Cache)CPU stays high together with slow clients
noderunner.exeExchange Search (Search Host Controller service)Busy after mailbox moves, new databases, reseeds or updatesBusy for days, or the content index isn't healthy
w3wp.exeOne per IIS app pool (OWA, EWS, ActiveSync, MAPI and more)Moderate, with peaks at logon timeOne pool pinned for hours
EdgeTransport.exeTransport worker processGrows with queue sizeQueues growing, back pressure
MSExchangeHMWorker.exeManaged Availability workerShort burstsSustained load or repeated recovery actions

High memory alone isn't a fault: Exchange sizes its caches to use the RAM it's given and keeps it. Real problems usually come from one of these:

  • Undersized or misconfigured hardware. For Exchange 2019 and SE, Microsoft recommends at least 128 GB of RAM for the Mailbox role (Exchange supports up to 256 GB) and up to two processor sockets on physical servers; add the High performance power plan and a fixed-size page file. Dynamic memory and memory overcommit aren't supported for Exchange virtual machines.
  • One client or application hammering a protocol, such as an EWS integration polling every mailbox or a misbehaving mobile device.
  • Search catching up after a migration or an index rebuild.
  • File-level antivirus scanning Exchange databases, logs and processes without the exclusions Microsoft documents.
  • Bugs fixed in updates. For example, lock contention in MSExchangeMapiMailboxAppPool could hold CPU at 100% for over an hour; the fix shipped in Exchange 2019 CU7 and Exchange 2016 CU18.

How to fix it#

1. Rule out configuration first#

Run the Health Checker and fix what it flags (power plan, memory, page file, processors, build) before chasing processes. For the page file, Exchange 2019 and SE want the minimum and maximum both set to 25% of installed RAM; Exchange 2016 wants RAM plus 10 MB, capped at 32,778 MB. Configure only one page file.

2. Identify the process and what it serves#

PowerShell
(Get-Counter '\Process(*)\% Processor Time').CounterSamples |
  Where-Object InstanceName -notin '_total','idle' | Sort-Object CookedValue -Descending |
  Select-Object -First 10 InstanceName, @{n='CPU %';e={[math]::Round($_.CookedValue / $env:NUMBER_OF_PROCESSORS, 1)}}
& "$env:windir\system32\inetsrv\appcmd.exe" list wp

Per-process counters add up across all logical processors, so the script divides by their number. appcmd list wp maps each w3wp.exe process ID to its app pool, such as MSExchangeServicesAppPool (EWS) or MSExchangeSyncAppPool (ActiveSync). Task Manager's Command line column shows the same.

3. Act on the cause#

  • An IIS app pool: find out who is calling it. Exchange's IIS logs are in C:\inetpub\logs\LogFiles\W3SVC1 (Default Web Site) and W3SVC2 (Exchange Back End) by default. The script below lists the top EWS callers in the newest front-end log. Fix or throttle the app or device it reveals instead of just recycling the pool.
  • noderunner.exe: run Get-MailboxDatabaseCopyStatus -Server EX01 | Format-Table Name, Status, ContentIndexState. If indexing is catching up after a migration, let it finish; if an index is Failed, repair it rather than stopping the search services.
  • EdgeTransport.exe: check Get-Queue | Sort-Object MessageCount -Descending and the back pressure state with Get-ExchangeDiagnosticInfo -Server EX01 -Process EdgeTransport -Component ResourceThrottling.
  • MSExchangeHMWorker.exe: check what Managed Availability keeps doing, as shown in my Managed Availability deep dive.
  • Everything slow at once: confirm the antivirus exclusions and the build, then install the latest cumulative and security updates.
PowerShell
$log = Get-ChildItem 'C:\inetpub\logs\LogFiles\W3SVC1' -Filter *.log | Sort-Object LastWriteTime | Select-Object -Last 1
$fields = ((Get-Content $log.FullName -TotalCount 5) -match '^#Fields:') -replace '^#Fields: ' -split ' '
Get-Content $log.FullName | Where-Object { $_ -notmatch '^#' } | ConvertFrom-Csv -Delimiter ' ' -Header $fields |
  Where-Object { $_.'cs-uri-stem' -like '/EWS/*' } | Group-Object 'cs-username','cs(User-Agent)' |
  Sort-Object Count -Descending | Select-Object -First 10 Count, Name

4. Capture evidence for intermittent spikes#

Exchange already writes performance logs to %ExchangeInstallPath%Logging\Diagnostics\DailyPerformanceLogs; open them in Performance Monitor to look back at a spike. For a targeted capture, use ExPerfWiz from Microsoft's CSS-Exchange scripts (its page lists Exchange 2013, 2016 and 2019):

PowerShell
.\ExPerfWiz.ps1     # run elevated; loads the ExPerfWiz functions
New-ExPerfWiz -FolderPath D:\ExPerfWiz -StartOnCreate
Stop-ExPerfWiz      # stop it this way, not from the Performance Monitor GUI

By default it samples every 5 seconds and stops after 8 hours. Note the times users report slowness so you can line them up with the counters.

Verify the fix#

  • Get-Counter '\Processor(_Total)\% Processor Time' -SampleInterval 5 -MaxSamples 12 stays well clear of saturation during business hours.
  • \Memory\Available MBytes is stable and no new event 2004 appears in the System log.
  • Queues drain in Get-Queue and transport reports no back pressure.
  • Get-HealthReport -Identity EX01 | Where-Object AlertValue -ne 'Healthy' returns nothing, and the Health Checker is clean.

Prevent it next time#

  • Size servers with Microsoft's Exchange sizing calculator and give virtual machines static, reserved memory.
  • Give each integration its own account so IIS logs show who is calling.
  • Re-check antivirus exclusions after every security agent update.
  • Stay current on updates. Exchange 2016 and 2019 have been out of support since 14 October 2025, so plan your move if you're still on them.

References#

Revision history: Oct 2026 — re-checked against Microsoft Learn: 2 corrections.

Written and checked against current Microsoft Learn documentation. Test changes with a pilot group before rolling them out to everyone, and if an admin center path has moved since, search for the setting name instead.

Spotted a mistake, or did this fix work differently for you? Email me or message me on LinkedIn — corrections are credited in the article.

Written by

Omer Eltayeb

Intune Subject Matter Expert in Cairo, Egypt, former Microsoft Cloud Solutions Architect, Microsoft Certified Trainer and Microsoft Innovative Educator Expert (2024–26) and Microsoft Elevate Educator Expert (2026–27). I share practical, step-by-step guides, study plans, scripts and toolkits for Microsoft Intune, Configuration Manager, Microsoft Entra ID, Microsoft Defender, Exchange and Microsoft 365 with the community.

Microsoft Certified Trainer (MCT) 2026Microsoft Innovative Educator Expert 2025–2026Microsoft Elevate Educator Expert 2026–2027ISC2 Certified Information Systems Security Professional (CISSP)Microsoft 365 Certified: Enterprise Administrator Expert (MS-102)