LSASS High CPU and Memory: Causes, Isolation, and Fixes
When the Local Security Authority Subsystem Service chokes a domain controller, the process itself is rarely broken — it is working furiously on behalf of misconfigured clients, unindexed queries, or runaway authentication loops.
Unindexed filters, broad wildcards, and runaway service accounts forcing full directory table scans across thousands of objects.
NTLM pass-through storms, unconstrained Kerberos loops, and Netlogon secure channel queue saturation choking worker threads.
The ESE buffer cache legitimately holding NTDS.dit pages in RAM versus true kernel or module memory exhaustion.
What You’re Seeing
The symptoms usually strike without warning during standard business hours or right after an application deployment. An alert fires from your monitoring platform indicating that a production Domain Controller has sustained 95% to 100% CPU utilisation for fifteen consecutive minutes. Administrative RDP sessions become sluggish, hanging for thirty seconds at “Securing remote connection…” before presenting a desktop. Client logons start timing out across the site, and member servers log Event 5719 or Event 1058 complaining that no domain controller is available to service policy or authentication.
When you finally connect to the console and open Task Manager or Resource Monitor, the culprit stands out immediately:
# Task Manager / Details tab
Name PID CPU Working Set Commit Size Description
lsass.exe 684 98% 14,218,440 K 15,102,912 K Local Security Authority Subsystem Service
# Performance Monitor counter alert
\Process(lsass)\% Processor Time : 98.42
\Process(lsass)\Working Set : 14.55 GB
\System\Processor Queue Length : 18
In the Directory Service and System event logs, you will frequently observe correlated warning events reporting resource constraints and delayed operations:
# Directory Service Log - Event ID 1644 (When Field Engineering logging is enabled)
Log Name: Directory Service
Event ID: 1644
Task Category: Field Engineering
Level: Information
Description: The directory service encountered an expensive search request.
Starting node: DC=corp,DC=example,DC=com
Filter: (&(objectCategory=person)(objectClass=user)(mail=*smith*))
Search scope: Whole Subtree
Attribute selection: mail, distinguishedName, memberOf
Entries examined: 84210
Entries returned: 12
Time (msecs): 4820
Client: 10.10.20.145:51204
Binding: LDAP
User: CORP\svc-assetscanner
# System Log - Event ID 5816 / 5817 (Netlogon throttling)
Log Name: System
Event ID: 5817
Source: NETLOGON
Level: Warning
Description: The Netlogon service cannot service authentication requests for user CORP\jdoe
from \\WORKSTATION04 because the API has been exhausted.
What It Actually Means
Think of LSASS as the front-desk security and reception team at a massive corporate headquarters. The receptionists do not generate internal paperwork on their own whim; their entire workload is dictated by the queue of visitors standing in the lobby demanding badges, background checks, building directory lookups, and room access. If a tour bus unloads three thousand tourists who all ask for directions to a room that does not exist, the front desk becomes completely paralysed. The staff members are not broken — they are drowning under unreasonable external demand.
Technically, lsass.exe (Local Security Authority Subsystem Service) is a core Windows container process that hosts multiple independent dynamic-link libraries responsible for security and identity services. On a domain controller, LSASS hosts:
ntdsa.dll (the Active Directory Directory Services engine, handling LDAP queries, schema evaluation, and directory replication), esent.dll (the Extensible Storage Engine database manager for NTDS.dit), kerberos.dll (the Key Distribution Center handling Ticket Granting Service and Ticket Granting Ticket requests), msv1_0.dll and netlogon.dll (handling NTLM authentication, pass-through validation, and domain trusts), and schannel.dll (handling TLS handshakes for LDAPS on port 636 and 3269).
When LSASS consumes excessive CPU or memory, the root cause invariably lives inside one of these specific subsystems. High CPU is usually driven by either inefficient LDAP queries forcing unindexed database searches across hundreds of thousands of records, or an NTLM authentication flood overwhelming single-threaded Netlogon worker queues.
High memory usage, on the other hand, is frequently misunderstood. Active Directory uses the ESE database engine, which implements aggressive read-caching. Under normal conditions, LSASS will read database pages from NTDS.dit into RAM and keep them in the Database Cache to avoid slow disk I/O. If your domain controller has 16 GB of RAM and NTDS.dit is 8 GB, LSASS will happily consume 10 GB of RAM. This is healthy, expected behaviour, not a memory leak. A genuine memory leak occurs only when the Private Bytes counter continuously ascends without plateaus and fails to release memory when other operating system components demand it.
How to Diagnose
Diagnosing LSASS performance problems requires a structured approach from high-level process baselines down to specific LDAP filters and network callers.
# Step 1: Query process metrics and distinguish working set from database cache
Get-Counter -Counter @(
'\Process(lsass)\% Processor Time',
'\Process(lsass)\Working Set',
'\Process(lsass)\Private Bytes',
'\Database(lsass)\Database Cache Size (MB)'
)
# Step 2: Start the built-in Active Directory Diagnostics Data Collector Set
logman start "system\Active Directory Diagnostics" -ets
# Allow the collector to gather data under load for 2 to 5 minutes, then stop it
logman stop "system\Active Directory Diagnostics" -ets
The compiled report is saved under %SystemDrive%\PerfLogs\System\Active Directory Diagnostics\<Date-Time>\report.html. Open this report and review the Directory Service section: it automatically highlights the top IP addresses sending LDAP requests and flags queries with excessive elapsed execution times.
To isolate the exact LDAP queries and client IP addresses causing high CPU, enable verbose Field Engineering diagnostic logging:
# Step 3: Enable Field Engineering logging in the registry (Value 5 = Verbose)
Set-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Services\NTDS\Diagnostics" -Name "15 Field Engineering" -Value 5 -Type DWord
# Step 4: Configure diagnostic thresholds for expensive and inefficient searches
# Flag queries returning or visiting more than 10,000 entries
Set-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Services\NTDS\Parameters" -Name "Expensive Search Results Threshold" -Value 10000 -Type DWord
# Flag queries examining more than 1,000 unindexed entries per returned entry
Set-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Services\NTDS\Parameters" -Name "Inefficient Search Results Threshold" -Value 1000 -Type DWord
# Flag queries taking longer than 1,000 milliseconds (1 second) to complete
Set-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Services\NTDS\Parameters" -Name "Search Time Threshold (msecs)" -Value 1000 -Type DWord
# Step 5: Read the latest Event ID 1644 entries from the Directory Service log
Get-WinEvent -FilterHashtable @{LogName='Directory Service'; Id=1644} -MaxEvents 5 |
Select-Object TimeCreated, Message | Format-List
If Event ID 1644 does not record excessive LDAP activity, the CPU spike is likely driven by authentication traffic. Verify NTLM concurrency bottlenecks using Netlogon debug logging:
# Step 6: Enable Netlogon debug logging to detect authentication queue delays
nltest /dbflag:0x20000004
# Inspect the live Netlogon log for authentication requests and wait times
Get-Content -Path "$env:SystemRoot\debug\netlogon.log" -Tail 30
# Turn off Netlogon debug logging immediately once data is gathered
nltest /dbflag:0x0
15 Field Engineering back to 0 once your diagnostic session ends. Leaving verbose logging active under high production load will rapidly roll the Directory Service event log and generate unnecessary disk I/O overhead.
Common Causes
The table below details the most frequent root causes of LSASS CPU and memory degradation, how to confirm each scenario, and the required fix.
| Cause | How to Confirm | Fix |
|---|---|---|
| Unindexed or Wildcard LDAP Queries | Directory Service Event 1644 records high Entries examined with low Entries returned, pointing to a specific client IP and filter like (mail=*term*). |
Instruct the application owners to rewrite queries without initial wildcards, or index the attribute in the Active Directory Schema snap-in: Set-ADObject -Identity "CN=mail,CN=Schema,CN=Configuration,DC=corp,DC=com" -Replace @{searchFlags=1}. |
| NTLM Pass-Through Flood | System log warnings Event 5816, 5817, 5818, or 5819 from source NETLOGON; Perfmon counter \Netlogon(_Total)\Semaphore Waiters elevated above zero. |
Migrate client applications and web services from NTLM to Kerberos authentication, and temporarily increase the Netlogon semaphore limit: Set-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Services\Netlogon\Parameters" -Name "MaxConcurrentApi" -Value 10 -Type DWord. |
| Unpooled LDAPS Connections | Network captures show rapid TCP three-way handshakes and TLS negotiations on port 636 followed by immediate TCP FIN packets from a single server. | Configure the client application or identity sync tool to implement LDAP connection pooling rather than establishing a fresh TLS handshake for every individual user lookup. |
| ESE Database Buffer Cache (Normal) | \Process(lsass)\Working Set is high (e.g. 12 GB), but \Database(lsass)\Database Cache Size (MB) matches the database footprint, and Private Bytes remains stable. |
No fix is required because this is healthy directory caching behaviour; ensure the domain controller has enough physical RAM to leave at least 4 GB available for OS services. |
| True LSASS Memory Leak | \Process(lsass)\Private Bytes continuously increases over days without stabilising, failing to drop even under heavy operating system memory pressure. |
Capture a memory dump using procdump.exe -ma lsass.exe, identify leaked modules via WinDbg heap analysis, update third-party antivirus/EDR filter drivers, and apply the latest cumulative Windows Server quality updates. |
| Corrupt AD-Integrated DNS Records | DNS Server service triggers repeated updates; \Process(lsass)\% Processor Time remains high while dns.exe communicates constantly with LSASS via LPC. |
Scavenge stale DNS resource records and verify that automated client registrations are not creating circular or multi-thousand-record round-robin A records for a single host name. |
The Fix: Resolving an Inefficient LDAP Search Storm
In over seventy percent of real-world domain controller CPU outages, the root cause is an enterprise application (such as an HR directory sync, ServiceNow connector, or third-party asset scanner) running inefficient LDAP queries. Here is how to trace and terminate that condition end-to-end:
First, examine your collected Event 1644. Identify the Client IP address and the User account executing the search. For example:
Starting node: DC=corp,DC=example,DC=com
Filter: (&(objectCategory=person)(employeeNumber=94821))
Entries examined: 120540
Entries returned: 1
Client: 10.10.50.82:49312
User: CORP\svc-workday-sync
In this scenario, the application requested an object matching employeeNumber=94821. Because employeeNumber is not indexed by default in Active Directory, the ESE database engine had to load and inspect 120,540 directory objects across the entire directory partition just to locate a single user. When this application runs twenty concurrent worker threads, LSASS immediately pins all CPU cores at 100%.
You have two options to permanently resolve this:
Option 1: Index the attribute in the Schema. If the application must query this attribute frequently, adding an index allows the directory engine to locate the record via an indexed b-tree lookup in milliseconds rather than scanning the table:
# Import the Active Directory module
Import-Module ActiveDirectory
# Register the Schema Management DLL if using the GUI MMC
regsvr32.exe schmmgmt.dll
# Alternatively, set the searchFlags attribute directly on the Schema attribute object
# searchFlags value 1 enables indexing (INDEX_ATT)
$schemaDN = (Get-ADRootDSE).schemaNamingContext
Set-ADObject -Identity "CN=Employee-Number,$schemaDN" -Replace @{searchFlags=1}
Option 2: Terminate or throttle the client session. If the query is poorly written or scanning attributes with initial wildcards (e.g. (cn=*john*), which cannot use a standard index), locate the server at 10.10.50.82 and stop the offending service or scheduled task until the development team rewrites the LDAP query.
Finally, clean up your diagnostic registry keys to return the domain controller to its standard logging baseline:
# Reset Field Engineering logging to default 0
Set-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Services\NTDS\Diagnostics" -Name "15 Field Engineering" -Value 0 -Type DWord
# Reset search thresholds to 0 (disabled)
Set-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Services\NTDS\Parameters" -Name "Expensive Search Results Threshold" -Value 0 -Type DWord
Set-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Services\NTDS\Parameters" -Name "Inefficient Search Results Threshold" -Value 0 -Type DWord
Set-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Services\NTDS\Parameters" -Name "Search Time Threshold (msecs)" -Value 0 -Type DWord
How to Prevent It
Preventing LSASS degradation requires proactive directory policy configuration, proper capacity sizing, and baseline monitoring.
1. Configure LDAP Query Hardening and Timeouts: Use Active Directory Query Policies (configured via ntdsutil under the LDAP policies menu) to enforce limits on client queries. The default MaxPageSize is 1000 objects, but setting reasonable values for MaxQueryDuration (e.g. 120 seconds) prevents single rogue queries from locking database threads indefinitely.
2. Size DC Memory to Match NTDS.dit: To keep LSASS database caching healthy, ensure the domain controller has enough physical RAM to host the entire NTDS.dit database file plus operating system overhead. If NTDS.dit is 12 GB, provision the server with at least 24 GB to 32 GB of RAM. This keeps the \Database(lsass)\Database Cache % Hit counter at 99% or higher, minimising disk reads.
3. Monitor Event 1644 in Centralised SIEM: Instead of enabling verbose Field Engineering only during outages, establish moderate permanent thresholds (e.g. queries scanning over 50,000 objects or taking over 3 seconds) and forward Event ID 1644 to your centralised logging platform (Microsoft Sentinel, Splunk, or Elastic). This surfaces abusive application queries weeks before they trigger an operational outage.
Final Thoughts
High CPU and memory consumption in LSASS is almost never a mystery software bug that requires a server reboot. Because LSASS is the security foundation of Windows Server, it faithfully processes whatever traffic your enterprise infrastructure throws at it.
When you isolate the subsystem — checking whether the load originates from ntdsa.dll database lookups, netlogon.dll authentication queues, or genuine memory leakage — you transform an intimidating infrastructure emergency into a straightforward exercise in identifying an abusive client application or missing database index.
Next, we will explore Windows Server Storage Replica: block-level synchronous and asynchronous replication architecture for disaster recovery.