HomeNewsletterCommunityMVP FeedToolsArchiveBlogToday's NewsAboutServicesQuick Links Subscribe free
← Back to Blog
Windows Update Windows UpdateWSUSSUSDBIISWsusPoolSupersedencePatch ManagementWindows Server

The client is fine and your WSUS server is broken: the server-side diagnostic order to run before you touch another endpoint

IA
Imran Awan
23 August 2026

A ticket says a laptop is missing the August cumulative update. You check the client. The Windows Update service is running, the component store is clean, there is no pending reboot, the policy looks right, and Get-WindowsUpdateLog shows a scan that completed without an error. So you reset SoftwareDistribution, run SFC, and wait. Nothing changes.

Three days later you have re-imaged two devices, opened a case with your OEM, and the update is still missing. Then somebody looks at the WSUS server and finds that the update was declined during a cleanup pass eleven weeks ago.

Every client in that fleet was working correctly the whole time. They asked the server what they needed, the server answered honestly, and the answer was nothing. There is no client-side error for "the server told me I am fine", which is exactly why this failure mode eats days.

This post is the server-side diagnostic order. It is deliberately narrow: no client remediation, no DISM, no service resets. The rule is simple. Never re-image a client until you have proven the server is serving.

The short version

A WSUS client that reports zero applicable updates is usually telling you the truth about what the server said. Microsoft documents that a declined update is not offered to clients for evaluation or installation at all, and that declined updates are hidden from the console's default view — so the single most common root cause is invisible in the place you look first. Behind that sit four more server-side faults with documented mechanisms: expired updates auto-declined by a revision, supersedence chains that were never pruned (Microsoft's own threshold is 1,500 undeclined superseded updates before clients start suffering), a WsusPool application pool recycling against its default 1,843,200 KB private-memory limit and returning HTTP 503, and a content directory or SUSDB that has been left unmaintained for years. Every one of those produces a clean client and a confusing ticket. The order below checks approval state, then supersedence, then WSUS server health, then the server logs — and only then goes back to the endpoint.

The problem: the client is telling you the truth

The reason this failure is expensive is that it produces no error. A client that scans successfully and is offered nothing looks identical to a client that is fully patched.

Here is that identity on a real device. The block below is from a live Windows 11 Enterprise 25H2 machine, build 26200.9168, read out of the Microsoft-Windows-WindowsUpdateClient/Operational channel.

Client-side evidence — the line that proves nothing
# Real Event IDs captured read-only. OS 10.0.26200.9168, wuaueng.dll 1509.2607.1012.0. Log Name: Microsoft-Windows-WindowsUpdateClient/Operational Event ID: 26 Level: Information Message: Windows Update successfully found N updates. # That is a SUCCESS event. The agent reached the service, authenticated, # sent its criteria, and got a well-formed answer back. # # Now consider N = 0. Three completely different situations emit that # identical line: # 1. The device is genuinely fully patched. # 2. The device is excluded by a stale TargetReleaseVersion pin. # 3. The update it needs was DECLINED on the WSUS server. # # Nothing on the client can separate them. There is no Event ID for # "the server deliberately withheld an update from me".

That is the whole trap. Event 26 is a success record, so every client-side triage script treats it as green. Event 41 ("An update was downloaded") never arrives because there was nothing to download, and the absence of an event is not something a monitoring rule fires on.

The table below is the translation layer you need when the ticket lands. The left column is what you are told; the right column is the server-side reading that most teams never make.

What the ticket or dashboard saysThe client-side reading (usually wrong)The server-side reading (check this first)
"No updates available" on a device you know is behindBroken WU agent, corrupt datastore, bad policyThe update is declined, or expired and auto-declined, so the server does not offer it for evaluation at all
One update missing on every device in one groupDeployment ring misconfiguration on the clientsApproval state is Not approved for that computer group, or the group inheritance was never applied to children
Every device stopped reporting in the same weekMass agent failure, network changeThe WSUS web services are down — almost always a stopped or thrashing WsusPool application pool
Scans take 20+ minutes and sometimes failSlow disks, antivirus, WMIMetadata bloat: superseded updates never declined, SUSDB never reindexed
Detection succeeds but download failsBITS, proxy, TLSContent directory full, moved, or missing the documented NETWORK SERVICE permissions
WSUS console will not connect"Console problem, ignore it"Not a console problem. The admin site and the client web service share one application pool — if the console is down, your fleet is down

Look at the last row for a moment, because it is the single highest-value inference in this post. Microsoft's WSUS server-settings reference lists the IIS virtual directories created at setup: ClientWebService, ServerSyncWebService, ReportingWebService, SimpleAuthWebService, DssAuthWebService and WSUSAdmin. All six are documented as running in the WsusPool application pool.

So "the console cannot connect" and "no client can scan" are not two tickets. They are one fault reported by two different observers, and the console is the observer that happens to be sitting on your desk.

Watch out: the reflex fix — stop wuauserv, delete or rename C:\Windows\SoftwareDistribution, restart, rescan — destroys the only client-side record of what the server actually answered. The client datastore and the ETW traces under C:\Windows\Logs\WindowsUpdate\ are your evidence that the scan succeeded and returned nothing, which is what points you at the server in the first place. Related trap: Get-WindowsUpdateLog -ForceFlush stops the Update Orchestrator and Windows Update services in order to flush the trace buffers. It is a fine command, but it must never be the first thing you run, because it perturbs the state you are trying to measure. On a real 25H2 device this directory held 99 ETL files totalling 42.5 MB — that is the forensic record, and a SoftwareDistribution reset is a decision to throw it away.

One honest caveat before we go server-side, because this post is not an argument that the server is always at fault. Microsoft's own WSUS troubleshooting guidance is explicit that the console message "Computer hasn't reported status" is typically caused by the client, not the server: the machine is off, asleep, or off the network. That message is a reporting gap, not a serving failure, and it belongs in a different investigation. The failures in this post are the ones where the client demonstrably completed a scan.

Why it happens: five server-side faults that present as client faults

1. The update is declined — and declined updates are hidden by default

WSUS has three approval states that matter here, and the difference between two of them is the entire post.

Not approved is not the same as absent. Microsoft's update-operations documentation is clear that when an update is left unapproved, the server still lets clients evaluate whether they need it. The update shows up in compliance reporting as needed and not installed. That is the state you want for something you have not deployed yet, because it keeps the update visible in your reports.

Declined is different in kind. Declining removes the update from the default list and the server stops offering it to clients — not just for installation, but for evaluation. The client will never see it, will never report it as needed, and will never generate a compliance gap. Your dashboard goes green because the question was withdrawn, not because it was answered.

Now the part that turns a five-minute check into a three-day outage: declined updates only appear in the WSUS console's update list if you explicitly select Declined in the Approval filter under View. The default view hides them. So an admin who opens the console, searches for the KB, and finds nothing concludes the update never synchronised — when in fact it is sitting right there, declined.

Context: you can see this design assumption baked into the tooling. The Get-WsusUpdate cmdlet's -Approval parameter accepts exactly four values: Approved, Unapproved, Declined and AnyExceptDeclined. The existence of a dedicated "everything except declined" value tells you that filtering declined updates out is the expected default behaviour throughout the product. If your inventory or reporting script does not explicitly ask for Declined, it is not going to find your root cause. Note also the same cmdlet's -Classification parameter is limited to All, Critical, Security and WSUS — you cannot narrow it to Updates or Upgrades from PowerShell, so use All and filter on the returned objects.

2. The update expired, and a revision auto-declined it

The second cause is the same end state reached without anyone deciding anything.

WSUS updates are revised. Microsoft defines a revision as a version of an update that has changed — and gives expiry and changed applicability rules as the two examples. On the Advanced tab of Automatic Approvals there are two options that are on by default: automatically approve new revisions of approved updates, and automatically decline updates when a new revision causes them to expire.

Both defaults are correct. Microsoft recommends keeping them, because they are what stops the database filling with dead metadata. But the consequence is that Microsoft expiring an update upstream can silently transition it to Declined on your server, at a time of Microsoft's choosing, with no admin action and no notification. Weeks later, a device that legitimately needed that specific update gets offered nothing.

The documentation is equally blunt about the alternative: if you turn off automatic declining of expired updates, you have taken on the job of declining them manually on a periodic basis. There is no third option where the metadata just stays tidy on its own.

3. Supersedence chains that were never pruned

This is the slow one. It does not break a single update; it degrades every scan, for years, until scans start timing out.

Start with a fact that surprises people: WSUS does not automatically decline superseded updates when you approve the update that supersedes them. Microsoft states plainly that no such feature exists, and further advises against assuming a superseded update should be declined — a superseding update may support only newer OS versions, or have narrower applicability, so the older one can still be the correct answer for part of your fleet.

The result is that on a server nobody maintains, superseded metadata accumulates monotonically. Microsoft's WSUS best-practices guidance calls keeping superseded updates around longer than needed the leading cause of WSUS performance problems, and the maintenance guide gives a hard number you can measure yourself:

SUSDB — Microsoft's documented health query (read-only)
# Run against SUSDB. This is a SELECT-only query. It changes nothing. # Documented threshold: above 1500 undeclined superseded updates, # Microsoft states you get software-update problems on BOTH the # server and the client side. Select COUNT(UpdateID) from vwMinimalUpdate where IsSuperseded=1 and Declined=0 # The fuller census from the WSUS database-maintenance article breaks # the same view down into the columns that matter: Total Updates | Live Updates | Superseded | Superseded but not declined | Declined | Superseded & Declined | Obsolete Updates Needed to be cleaned # Microsoft's read on this output: an excessive number of superseded, # declined and obsolete updates often causes poor SUSDB health, and if # the last three columns run into the hundreds, run maintenance. # # Record these seven numbers every month. They are the only objective # trend line you have for WSUS health.

Why does server-side metadata volume hurt a client? Because of how a scan works. WSUS keeps a database-backed cache of update metadata and returns the delta since the client last checked in. Microsoft describes building that cache as expensive and very memory intensive. When a client has no usable prior state it must do a full scan instead of a delta, and the maintenance guidance notes transfers greater than 1 GB per client in that scenario, particularly on a poorly maintained server.

Multiply one gigabyte by a few thousand devices arriving after a Patch Tuesday and you have what Microsoft calls a scan storm. Which leads directly to the next fault, because a scan storm is how the application pool dies.

4. WsusPool recycles under load and answers HTTP 503

If you only remember one server-side check from this post, make it this one. It is the most common cause of a whole fleet appearing to break its Windows Update client simultaneously, and it is a single number in IIS.

The mechanism is documented end to end. WSUS builds that expensive metadata cache inside the IIS worker process. The WsusPool application pool has a default private-memory limit. Cache building crosses it. IIS recycles the pool to enforce the limit. The recycle discards the cache. The next client request starts rebuilding it. Under sustained load that loop never converges, and clients get HTTP 503 back instead of update metadata.

The scale of the mismatch is the interesting part. Microsoft's best-practices article notes that an environment with around 17,000 cached updates may need more than 24 GB of memory while the cache is being built, settling at around 14 GB. The default private-memory limit is 1,843,200 KB — about 1.76 GB. The default is roughly an order of magnitude below the documented working set of a large server.

Here is the documented recommended configuration, with the defaults it replaces:

WsusPool advanced settingRecommended valueDefault it replaces
Queue Length20001000
Idle Time-out (minutes)020
Ping EnabledFalseTrue
Private Memory Limit (KB)0 (unlimited)1,843,200 KB
Regular Time Interval (minutes)0 (no scheduled recycle)1740 (29 hours)

All five live in the same place: IIS Manager, Application Pools, select WsusPool, then Advanced Settings. Read them before you change them — the current values are diagnostic data.

Gotcha: Microsoft publishes two different numbers for Private Memory Limit and you will meet both. The WSUS best-practices article recommends 0, meaning unlimited, and disabling the virtual-memory limit alongside it. The WSUS messages-and-troubleshooting article, addressing an HTTP 503 caused by a stopped WsusPool, instead recommends raising the limit to 4 GB (4000000 KB) and notes you may need 8 GB (8000000 KB) or higher depending on the environment. Both are current Microsoft guidance and neither is wrong. 0 removes the failure mode entirely but hands WSUS an unbounded claim on server RAM; an explicit 4–8 GB ceiling keeps a bound while clearing the real working set. Pick deliberately based on whether that box does anything else, and write down which one you chose — the next person to open IIS Manager will otherwise "fix" it back.

The other reason to know this cold is that the client-side error codes point straight at it, if you can read them. Microsoft's Windows Update error reference maps HTTP status codes into WU_E_PT_* values:

Client error codeDocumented symbolic name and meaningWhat it means on the server
0x80244022WU_E_PT_HTTP_STATUS_SERVICE_UNAVAIL — HTTP 503, service temporarily overloadedThe signature of a recycling or stopped WsusPool. Start here
0x8024401CWU_E_PT_HTTP_STATUS_REQUEST_TIMEOUT — HTTP 408, server timed out waiting for the requestServer is alive but too slow to answer; metadata bloat or SUSDB contention
0x8024401FWU_E_PT_HTTP_STATUS_SERVER_ERROR — HTTP 500, internal server errorAn unhandled fault inside the web service. Go to the Application log and the IIS log for the same second
0x80244019WU_E_PT_HTTP_STATUS_NOT_FOUND — HTTP 404, requested URI not foundContent path or virtual directory wrong, or a missing MIME type for UUP content
0x80244010WU_E_PT_EXCEEDED_MAX_SERVER_TRIPS — round trips exceeded the maximum limitClassic bloated-metadata symptom: the client gives up before the paged scan finishes
0x80240039WU_E_TOO_MANY_RESYNC — the agent is asked by the server to resync too many timesServer-driven resync loop, often after a cleanup or a cookie/state reset
0x80244011WU_E_PT_SUS_SERVER_NOT_SET — the WUServer policy value is missing from the registryGenuinely client-side. This one is a policy problem, not a server problem
0x8024402CWU_E_PT_WINHTTP_NAME_NOT_RESOLVED — proxy or target server name cannot be resolvedName resolution or proxy, between client and server. Check both ends
Gotcha: read that published table carefully rather than trusting the HTTP number in the description. Microsoft's own reference maps 0x80244020 (WU_E_PT_HTTP_STATUS_NOT_SUPPORTED) to "HTTP status 500" and 0x80244023 (WU_E_PT_HTTP_STATUS_GATEWAY_TIMEOUT) to "HTTP status 503", even though the symbolic names correspond to 501 and 504. Trust the symbolic name over the HTTP number in the prose, and correlate against the actual sc-status value in the IIS log rather than reasoning from the doc text alone.

5. The content directory and the SUSDB

The last two are the ones that show up as "detection works, download fails" and "everything is just slow".

Storage first. When you store update files locally, Microsoft's documented figures are a minimum of 20 GB with at least 40 GB recommended, plus roughly 10 GB more per Windows version and processor architecture for on-premises Unified Update Platform content. Two architectures of one Windows release is therefore about 20 GB on top of your existing footprint. Content directories that were sized before UUP fill up, quietly, and BITS transfers start failing while metadata scans keep succeeding — which is precisely why detection and download can disagree.

Permissions are the other half of that. The WSUS server-settings reference is specific: the root of the drive holding WsusContent needs Read for the appropriate account, and the content directory itself needs Full Control for NT AUTHORITY\NETWORK SERVICE. Setup configures the latter; it does not configure the drive-root permission, and security software has been known to reset both. Get either wrong and BITS downloads fail.

Then the database. Microsoft's reindex article opens with the sentence that should be pinned above every WSUS server: the performance of large WSUS deployments degrades over time if the database is not maintained properly. Not "may degrade" — will. Index fragmentation and stale statistics on SUSDB are a client-visible problem because every client scan is a query against it.

Tip: before you touch anything, find out where SUSDB actually lives, because it changes every subsequent step. Read SQLServerName under HKEY_LOCAL_MACHINE\Software\Microsoft\Update Services\Server\Setup. A plain server name or server\instance means full SQL Server. A value containing ##WID (or ##SSEE on very old builds) means Windows Internal Database, and that changes your tooling completely: the WID connection string is the named pipe \\.\pipe\MICROSOFT##WID\tsql\query, the database file is SUSDB.mdf under %windir%\wid\data\, and WID cannot schedule its own maintenance because it has no SQL Server Agent — you drive it from Task Scheduler with SQLCMD. Worth knowing too that Windows Internal Database is itself now listed as deprecated in Windows Server, with SQL Server as the suggested replacement.

How to verify: the server-side order, step by step

Everything below is read-only. Nothing here declines, approves, deletes or restarts anything. Work the steps in order and stop at the first one that fails, because a failure upstream makes everything downstream unreadable.

1. Scope2. Is it answering?3. Approval state4. Supersedence counts5. WsusPool6. Content + SUSDB7. Server logs8. Back to the client

Step 1 — Scope the blast radius before you look at anything

This costs thirty seconds and eliminates most of the search space.

Step 2 — Prove the web services are answering

The client web service is the endpoint every scan hits. Ask it the same question a client would.

Server-side reachability — read-only
# Default WSUS ports are documented as 8530 (HTTP) and 8531 (HTTPS). # The only other supported pair is 80/443. Nothing else is supported. PS> Invoke-WebRequest -UseBasicParsing ` -Uri "http://wsus01.contoso.com:8530/ClientWebService/client.asmx" | Select-Object StatusCode, StatusDescription StatusCode StatusDescription ---------- ----------------- 200 OK # 200 = the pool is up and the service is bound. Move to step 3. # 503 = Service Unavailable. This is the fleet-down case. Go to step 5. # It maps to client error 0x80244022. # 404 = the vroot or content path is wrong, or a MIME type is missing. # Now read the application pool state. No change is made. PS> & "$env:SystemRoot\system32\inetsrv\appcmd.exe" list apppool "WsusPool" APPPOOL "WsusPool" (MgdVersion:v4.0,MgdMode:Integrated,state:Started) # state:Stopped is the documented most-likely cause of HTTP 503 here. # A pool that is Started but flapping is worse, because it looks healthy # in a single sample. Check the Application log for repeated recycles. # The documented health check. Writes results to the event log; run it, # then read the Application log rather than watching the console. PS> & "$env:ProgramFiles\Update Services\Tools\WsusUtil.exe" checkhealth

Note what a 200 here does and does not prove. It proves the pool is running and the endpoint is bound. It does not prove the server can answer a real scan, because a real scan makes the pool build the metadata cache. That is why step 5 still matters even when step 2 is green.

Step 3 — Read the approval state, with Declined explicitly included

This is the step people skip, and it is the one that closes most of these tickets.

Approval state — the check that finds the declined update
# Get-WsusServer with no parameters targets the local WSUS server. PS> $wsus = Get-WsusServer # THE key query. -Approval Declined is the only way to see these. # The console's default view hides them; so does any script that # uses the AnyExceptDeclined value. PS> Get-WsusUpdate -UpdateServer $wsus -Classification All ` -Approval Declined -Status Any | Where-Object { $_.Update.Title -match "KB5121003" } Title Classification Approved ----- -------------- -------- 2026-08 Cumulative Update for Windows 11 Security Updates Declined # There it is. The client was right. Nobody withheld this on purpose - # it was almost certainly swept up by a cleanup pass or auto-declined # when a revision expired it. # Compare against the same update as the server sees it undeclined: PS> Get-WsusUpdate -UpdateServer $wsus -Classification All ` -Approval AnyExceptDeclined -Status FailedOrNeeded | Measure-Object | Select-Object Count # -Status accepted values (from the cmdlet reference): NoStatus, # InstalledOrNotApplicable, InstalledOrNotApplicableOrNoStatus, # Failed, Needed, FailedOrNeeded, Any.

In the console the equivalent move is to set the Approval filter under View to Declined and refresh. If the KB appears there, you are done diagnosing: this was never a client fault, and no amount of client remediation would ever have fixed it.

While you are here, check the other approval trap. Approving an update for a parent computer group does not automatically change child groups — multi-select approvals default to keeping existing approvals, and children stay as they were unless you explicitly apply to children. A "missing on one whole ring" symptom is very often exactly this.

Step 4 — Measure supersedence and obsolescence

Run the census query from earlier. You are looking for two things: a "Superseded but not declined" figure above 1,500, and an obsolete-update count in the thousands. Either one means the server has never been maintained, and that alone explains slow or failing scans across the fleet.

Do not fix it yet. Record the numbers. They are your before-picture, and without them you cannot prove the fix worked.

Step 5 — Read the WsusPool configuration

Compare the live values against the recommended table above. Any pool still sitting at the 1,843,200 KB default on a server with more than a few hundred clients is a finding, not a configuration.

Also check whether Xpress metadata compression is enabled, because it materially affects scan bandwidth. It is configured in two places: a <scheme name="xpress"> entry under <httpCompression> in ApplicationHost.config pointing at C:\Program Files\Update Services\WebServices\suscomp.dll, and the registry value IIsDynamicCompression under HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Update Services\Server\Setup. If both are absent, Microsoft documents DynamicCompression.vbs in the WSUS setup folder as the way to enable it. Trade-off is explicit: Xpress saves bandwidth and costs CPU.

Step 6 — Content directory and database

Two reads. First, resolve ContentDir from the registry and check free space on that volume against the 20 GB minimum / 40 GB recommended figures plus your UUP overhead. Second, resolve SQLServerName to find out whether you are on WID or SQL Server.

The registry key is shared, so it is stated once here:

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Update Services\Server\Setup
ValueMeaningWhat to look for
ContentDirRoot under which update binaries and EULA files are stored. Update files themselves live in the WsusContent subfolderDoes the path still exist, and is the volume full? This is the number that explains "detection works, download fails"
TargetDirProduct installation location, for example C:\Program Files\Update ServicesWhere WsusUtil.exe (in Tools), the web services, and the SelfUpdate folder live
SQLServerNameThe database instance WSUS actually uses under normal operationContains ##WID or ##SSEE means Windows Internal Database. A bare name or server\instance means full SQL Server, possibly remote
SqlDatabaseNameName of the WSUS databaseDocumented as always SUSDB. The name is not configurable, so anything else means someone has been improvising
SqlAuthenticationModeHow WSUS authenticates to the databaseDocumented as always Windows authentication. WSUS does not support SQL Server authentication
IIsDynamicCompressionWhether Xpress metadata compression is enabled for the WSUS web servicesMissing here plus missing from ApplicationHost.config means compression is off and every scan costs more bandwidth
Context: that registry key is a locator, not a configuration store. Microsoft's server-settings reference states directly that these entries do not hold server configuration — all of it lives inside SUSDB.mdf. This matters more than it sounds. It means you cannot diagnose a WSUS misconfiguration by exporting the registry, and it means a registry-level "fix" cannot repair a WSUS configuration problem. It also means the documented warning applies with force: do not manage WSUS by writing to the database directly, because the resulting corruption may not surface until an upgrade fails. Use the console, the UpdateServices cmdlets, or the API. The SQL scripts Microsoft publishes for maintenance are the documented exception, not a licence to go poking.

Step 7 — Read the server-side logs, in this order

Three log sources, three different questions. Most people never open any of them.

LogDocumented locationWhat it answers
SoftwareDistribution.log%Program Files%\Update Services\LogFiles\SoftwareDistribution.logWhat the WSUS server itself did: synchronisation, manual import, and the TLS/SCHANNEL state it logged at startup
Application event logEvent Viewer, Windows Logs, ApplicationWhere WsusUtil.exe checkhealth writes its results, and where application-pool recycles and worker-process faults land
IIS access logs%SystemDrive%\inetpub\logs\LogFiles by default, per-site W3SVC* subfoldersExactly what HTTP status each client got, and how long each request took — the ground truth behind every WU_E_PT_* code
SoftwareDistribution.log — the two patterns worth grepping for
# WSUS logs its enabled SSL/TLS protocols at service start. To get a # fresh block: restart the WSUS service, run iisreset, open the console, # then read the log. Documented example output: SCHANNEL Protocol 'TLS 1.0' disabled SCHANNEL Protocol 'TLS 1.1' disabled SCHANNEL Protocols subkey for 'TLS 1.2' not found. Protocol is enabled # If those SCHANNEL lines are absent entirely on a Server 2012/2012 R2 # box, Microsoft's documented reading is that the update enabling TLS 1.2 # is not installed - it shipped only in the Monthly Rollup, so a # security-only patching policy never received it. # The other pattern: upstream sync and import failures. ProcessWebServiceProxyException found Exception was WebException. Action: Retry. Exception Details: System.Net.WebException: ... # This is a SERVER-to-Microsoft failure, not a client-to-server one. # It means new metadata never arrived. Your clients are scanning # perfectly against a catalogue that is weeks stale - which produces # exactly the same "0 updates" ticket as a declined update.
IIS log — correlating the client error code with the server truth
# Enable these W3C fields if they are not already on: sc-status, # sc-substatus, sc-win32-status, time-taken, cs-uri-stem. # W3C timestamps are UTC; the log directory default is # %SystemDrive%\inetpub\logs\LogFiles under a W3SVC* folder per site. date time cs-uri-stem sc-status time-taken 2026-08-21 03:14:07 /ClientWebService/client.asmx 503 12 2026-08-21 03:14:09 /ClientWebService/client.asmx 503 9 2026-08-21 03:14:11 /ClientWebService/client.asmx 503 11 2026-08-21 03:17:44 /ClientWebService/client.asmx 200 184213 2026-08-21 03:21:02 /ClientWebService/client.asmx 200 201884 # Read it as a story, not as rows. # The 503 burst is the pool down or mid-recycle. Every client that hit # the server in those seconds logged 0x80244022 and looked broken. # Then the 200s come back - but time-taken is ~184 and ~202 SECONDS. # That is the metadata cache being rebuilt from the database on the # first requests after a recycle. # # A 200 with a three-minute time-taken is not a healthy server. It is # a server about to time out the next client with 0x8024401C.

This is why the IIS log beats every client-side tool for this class of fault. It is the only place where you can see the server's answer, the status code, and the latency together, for every device, with timestamps you can correlate against a client's Event 26.

Step 8 — Only now, go back to the client

If steps 2 through 7 are all clean — the pool is stable, the update is approved and not declined, supersedence counts are sane, content and SUSDB are healthy, and the IIS log shows fast 200s for that specific client's IP — then and only then have you earned the right to investigate the endpoint. And the ticket is now a genuinely different investigation, with the server eliminated on evidence rather than assumption.

The fix: repair the server in the documented order

Reinstating a declined update

If step 3 found a declined update, the repair is small and reversible. In the console, set the Approval filter to Declined, refresh, select the update, right-click, choose Approve and accept the dialog. That returns it to Not approved — visible again, evaluated by clients again, reported on again. Then approve it for the right computer group as a separate, deliberate action.

One caveat with teeth: if a cleanup pass has already deleted the declined update from the database, it is gone from the All Updates view and reinstating is not an option. You then re-import it from the Microsoft Update Catalog, assuming it has not been expired or removed there. And note that in a Configuration Manager environment the extra step after reinstating is a resynchronisation of the software update point — otherwise the site database still does not know about it.

Fixing WsusPool

Apply the values from the table in whichever of the two documented directions you chose, then recycle the pool once, deliberately, and watch the IIS log time-taken column as clients come back. Expect the first requests after the recycle to be slow — that is the cache rebuilding, and it is normal. What you are looking for is whether latency settles or whether the pool crosses its limit and recycles again.

Watch out: setting Regular Time Interval to 0 and Idle Time-out to 0 means this pool now never recycles on its own. That is the documented recommendation and it is the right call for WSUS, but it changes your operational posture: a slow memory leak in the worker process no longer gets swept up by a nightly recycle, and nobody notices until the box starts paging. If you disable automatic recycling, you owe the server a memory alert in its place. "Following the documented best practice" is not the same as "no longer needs monitoring".

Running the maintenance, in the documented order

Microsoft's maintenance sequence has five steps and the order is not decorative — reindexing before declining is what stops the decline pass timing out.

  1. Back up SUSDB. Non-negotiable. Every later step deletes data.
  2. Create the custom indexes. Optional but recommended, and a one-time job per database. Two non-clustered indexes: nclLocalizedPropertyID on tbLocalizedPropertyForRevision, and nclSupercededUpdateID on tbRevisionSupersedesUpdate. Microsoft's note is that they greatly improve performance of subsequent cleanup operations. Re-running the script on a database that already has them raises a duplicate-index error, which is harmless.
  3. Reindex SUSDB. Microsoft's published T-SQL identifies fragmented indexes, rebuilds or reorganises them based on page density and fragmentation, and then updates statistics via sp_updatestats.
  4. Decline superseded updates. Either the WSUS console, or the published Decline-SupersededUpdatesWithExclusionPeriod.ps1 script, or the SQL alternative built on spDeclineUpdate. Run the script with -SkipDecline first, every time, to get a count of what it would do.
  5. Run the Server Cleanup Wizard (or Invoke-WsusServerCleanup). Then reindex again, because the decline and cleanup passes will have churned the indexes.

The Cleanup Wizard's six documented behaviours are worth knowing precisely, because several of them have thresholds that explain why an update you expected to be cleaned up was not:

That five-condition test is the answer to "why is this superseded update still here". Most often the last condition is unmet: the replacement was never approved for a group, so WSUS correctly refuses to decline the thing it would replace. There is a related trap with automatic approvals — updates approved by an auto-approval rule stay in an Approved state and the wizard will not remove them, so an admin has to set them to Not approved first to make them eligible.

Invoke-WsusServerCleanup — dry run first, one switch at a time
# Documented as having the same impact as the console Cleanup Wizard, # with the same options exposed as parameters. # The six switches and what each one does: # -CleanupObsoleteComputers deletes obsolete computers from the DB # -CleanupObsoleteUpdates deletes obsolete updates from the DB # -CleanupUnneededContentFiles deletes unneeded update files # -CompressUpdates deletes obsolete update revisions # -DeclineExpiredUpdates declines expired updates # -DeclineSupersededUpdates declines superseded updates # ALWAYS start with -WhatIf. The cmdlet supports it; use it. PS> Get-WsusServer | Invoke-WsusServerCleanup -CleanupObsoleteUpdates -WhatIf # On a neglected server, run ONE option at a time and expect timeouts. PS> Get-WsusServer | Invoke-WsusServerCleanup -CleanupObsoleteUpdates Obsolete Updates Deleted: 62 Obsolete Computers Deleted: 0 # Microsoft's guidance for a server that has never been cleaned: # - the first pass may need several attempts before it completes # - it may take multiple hours or days # - if the wizard keeps timing out, reindex first, then use the # documented spGetObsoleteUpdatesToCleanup / spDeleteUpdate loop # - the second cleanup, 30 days later, is your real baseline for # how long this normally takes. Do not automate before then. # # Direction matters in a hierarchy: # CLEANUP runs bottom-up (downstream/replica servers first) # DECLINE runs top-down # Disable scheduled synchronisation for the whole window, or a sync # will re-populate what you just removed.
Watch out: the Server Cleanup Wizard also deletes the private update files you imported by hand from the Microsoft Update Catalog, and Microsoft's documentation states you must re-import them afterwards. If your environment depends on manually imported updates — preview updates, out-of-band fixes, anything that does not synchronise automatically — write that list down before you run cleanup. There is a second edge here too: in a hierarchy, running cleanup on an upstream server before every downstream server has been cleaned can leave upstream and downstream databases mismatched, which then causes synchronisation failures between them. Bottom-up, every time.
Tip: the honest exit criterion for a badly neglected server is documented, and it is worth knowing before you commit a weekend. Microsoft's database-maintenance article says the automatic maintenance can take anything from under a minute to several days, and that if you cannot get it to complete successfully you need to create a new SUSDB. Rebuilding is a legitimate documented option, not an admission of failure — the trade-off is a long initial synchronisation and the fact that every client then has to do a full scan against a fresh database rather than a differential one. Decide up front how many hours you will spend before you take that route, and note that the full-scan cost is exactly the scan-storm risk described earlier.

The elephant: WSUS is on a deprecation path

Context: be accurate about this, in both directions. Microsoft's WSUS overview and the Windows Server removed-and-deprecated-features list both state that WSUS is deprecated and no longer adding new features, and both state that it continues to be supported for production deployments and receives security and quality updates per the product lifecycle. The Windows Server 2025 entry adds that all existing capabilities and content remain available. Microsoft's own definition of deprecation on that page is that the component still ships, is still supported for production, and still gets security and quality updates — deprecated is not removed, and the WSUS role is still listed as supported on Windows Server 2016, 2019, 2022 and 2025 for Windows client servicing. So: do not tell your management that WSUS has been removed, because it has not been. Do tell them it will not get better, that Microsoft points at Windows Autopatch, Microsoft Intune and Azure Update Manager as the forward path, and that the plumbing described in this post is now the plumbing you maintain rather than the plumbing Microsoft improves.

Two concrete consequences that are already biting, both worth checking on your own estate.

First, driver synchronisation. Microsoft published a Windows IT Pro Blog post announcing the deprecation of WSUS driver synchronisation, and then published a second post titled "Continuing WSUS support for driver synchronization". Read both before you plan around either — the pair is a useful reminder that a deprecation date you memorised eighteen months ago may not be the current position, and that the only trustworthy answer is the live post.

Second, hardening. Microsoft published a servicing note that WSUS on Windows Server 2025 is removing dependencies on unsupported code, including binaries WSUS used to update the Windows Update SelfUpdate service on devices — starting with the September 2025 security update. The documented impact is narrow, affecting the updating of Windows Server 2012 and 2012 R2 endpoints on extended security updates, and Microsoft documents a temporary workaround involving copying the SelfUpdate folder from an older supported WSUS version and adding it as a virtual directory. Narrow or not, it is the shape of what deprecation looks like in practice: server-side changes that surface as client-side update failures.

Which is the argument of this whole post, restated. As the platform stops evolving, the proportion of "client" failures that are actually server failures goes up, not down.

Proof it worked: what to capture before and after

The failure mode here is invisible, so the fix is invisible too unless you measure it. Capture these before you change anything, and again a full detection cycle later.

SignalWhere to get itWhat "fixed" looks like
Declined-update countGet-WsusUpdate -Approval Declined, or the console with the Declined filterThe specific KB is no longer in the list; the total no longer contains anything you still need
Superseded but not declinedSUSDB census queryComfortably below the documented 1,500 threshold and trending down month over month
Obsolete updates to cleanspGetObsoleteUpdatesToCleanup row count in the census queryHundreds at most, not thousands
HTTP status distributionIIS log, sc-status on /ClientWebService/client.asmxNo 503s at all. That is the bar, not "fewer 503s"
Scan latencyIIS log, time-taken on the same URIStable and in the low seconds after the post-recycle warm-up, not minutes
Pool recyclesApplication event logNone unexplained. If you disabled scheduled recycling, any recycle at all is now a signal
Content volume free spaceVolume holding ContentDirHeadroom above the 20 GB minimum / 40 GB recommended plus your UUP overhead
Client-side confirmationMicrosoft-Windows-WindowsUpdateClient/Operational on a sample deviceEvent 26 with a non-zero count, followed by Event 41
Client-side confirmation — the same channel, a different answer
# Same device, same channel, same event IDs as the very first block. # Nothing on the client changed. The server started serving. Log Name: Microsoft-Windows-WindowsUpdateClient/Operational Event ID: 26 Windows Update successfully found N updates. # N > 0 Event ID: 41 An update was downloaded. # Then, if the update installs and stages, the Setup log picks it up: Log Name: Setup Event ID: 2 Package <KB> was successfully changed to the Staged state. # TIMING - do not judge this in five minutes. Automatic Updates is # documented as polling the WSUS server for approved updates every # 22 hours minus a random offset, and the detection interval is # configurable from 1 to 22 hours. Force a detection on ONE test # device to confirm the fix, then let the fleet come to you. # A fleet-wide forced scan right after a WSUS repair is how you # manufacture the scan storm you just finished fixing.

Two closing notes on interpreting the after-picture.

Event 26 with a non-zero count on one test device is proof the server is now serving. It is not proof the fleet is compliant — compliance follows the detection cycle, so give it a day before you read the dashboard as truth.

And keep the census query. Seven numbers, once a month, in a spreadsheet, is the entire early-warning system for a technology that Microsoft has stopped improving. The next person to be handed a "broken client" will thank you for the trend line.

References

Was this post helpful?
React below — no account needed
Share this post
LinkedIn X / Twitter Reddit Bluesky

More from EndpointWeekly

Windows Update
Which Update Service Is This Device Actually Registered Against?…
Before troubleshooting why a device gets the wrong updates, enumerate the registered…
Windows Update
The KB installed fine and is still being offered: supersedence,…
One 25H2 device held 199 Superseded, 121 Installed and 95 Staged packages while…
Windows Update
Decoding WUfB deferrals: why your 7-day ring is really a 37-day…
Your update ring says a 7-day quality deferral; the device is 37 days behind. Learn to…