Active Directory · Troubleshooting

Stale DNS Records After a Domain Controller Decommission

A decommissioned domain controller keeps showing up in DNS — clients still try to reach it, SRV records still list it — because scavenging has several safety valves designed to stop exactly the kind of automatic cleanup you now want, and forced removals skip DNS entirely.

Quick idea: Windows DNS only deletes a record automatically through aging and scavenging, a mechanism with a timestamp, a no-refresh window, a refresh window, and a replication safety check — all disabled by default and all designed to protect records, not remove them. A decommissioned DC’s records survive because either scavenging was never fully configured, or the decommission itself was forced and never touched DNS in the first place.
Aging

The timestamp Windows DNS stamps on dynamically registered records so it can tell old from current.

Scavenging

The cleanup pass that deletes records whose timestamp has aged past the zone’s refresh windows.

_msdcs

The forest-wide zone holding the SRV records and per-DC GUID CNAMEs that DC Locator depends on.

Introduction

A domain controller gets decommissioned — demoted properly, or pulled from production after hardware failure — and weeks later its name is still resolving. nslookup still returns it as an authoritative DC. A monitoring tool still tries to bind to it. Someone opens DNS Manager and finds its host record, its SRV entries under _msdcs, sitting there as if nothing happened.

This is not corruption and it is not a DNS bug. Windows DNS was deliberately built to be conservative about deleting records, because an aggressive cleanup that removes a record still in use breaks name resolution for whoever depends on it. That conservatism is exactly what leaves a decommissioned DC’s records behind unless you either configured scavenging correctly in advance, or clean the records up by hand.

What You’re Seeing

The decommissioned DC’s host (A) record, and its SRV records under the forest’s _msdcs zone, still resolve as if the server were alive:

# The retired DC still has an A record
C:\> nslookup dc03.corp.example.com
Name:    dc03.corp.example.com
Address: 10.10.4.23

# And it's still listed as a DC locator target
C:\> nslookup -type=SRV _ldap._tcp.dc._msdcs.corp.example.com
_ldap._tcp.dc._msdcs.corp.example.com  SRV service location:
          priority   = 0
          weight     = 100
          port       = 389
          svr hostname = dc03.corp.example.com

# Its per-DC GUID CNAME under _msdcs is also still there
C:\> nslookup -type=CNAME 3f2504e0-4f89-11d3-9a0c-0305e82c3301._msdcs.corp.example.com
Key point: Clients round-robin through every SRV record DNS hands back. A stale entry for a dead DC doesn’t just sit there cosmetically — it costs every client a connection timeout before it falls through to a working DC, which is exactly the kind of intermittent slowness that’s hard to pin down later.

What It Actually Means

Every dynamically registered DNS record in an aging-enabled zone carries a time stamp. When a client refreshes it — the default Windows DNS Client re-registers every 24 hours — the time stamp resets. Scavenging deletes a record only once record time stamp + no-refresh interval + refresh interval is less than the current time, and only if aging and scavenging are enabled at three separate layers: the individual record, the zone, and at least one server. Miss any one of those, and nothing gets deleted, no matter how old the record looks.

Records created manually, or copied in from a non-dynamic source, get a time stamp of zero — Windows treats that as “never age this” and it is excluded from scavenging permanently unless you explicitly reset it. A domain controller’s own DNS records are usually dynamically registered by the Netlogon service, so they are normally eligible. But decommissioning by force — dead hardware, a corrupted install, anything that skips a clean Remove-ADDSDomainController — never sends the deregistration request, so the records are left exactly as they were, waiting for scavenging to eventually catch up.

In simple terms: DNS doesn’t know a DC is gone unless something tells it. A graceful demotion tells it. A forced removal, a dead server, or a hypervisor deletion does not — DNS just keeps repeating the last thing it was told.

Even when scavenging is fully configured, there is one more safety valve specific to this scenario: a DNS server won’t scavenge a zone unless its Active Directory partition has replicated with at least one partner since the zone’s refresh interval last elapsed. This exists so a DC that has been offline for a while doesn’t wake up and scavenge records that are current elsewhere in the domain — but it means that as long as the decommissioned DC’s old replication partner metadata still looks unresolved, scavenging can silently stop running at all, on any zone, until that’s cleared up.

How to Diagnose

Work from what DNS shows you outward to what scavenging is actually doing.

# 1. Confirm the stale records exist and where
nslookup -type=SRV _ldap._tcp.dc._msdcs.corp.example.com
Get-DnsServerResourceRecord -ZoneName "_msdcs.corp.example.com" -RRType Srv

# 2. Confirm the decommissioned DC is actually gone from AD
nltest /dclist:corp.example.com

# 3. Check whether aging/scavenging is even enabled - server level
Get-DnsServerScavenging

# 4. Check whether it's enabled on the specific zone
Get-DnsServerZoneAging -Name corp.example.com

# 5. Check the DNS Server event log for the last scavenging pass
# Event 2501 = records were deleted. Event 2502 = cycle ran, nothing deleted.
Get-WinEvent -LogName "DNS Server" | Where-Object { $_.Id -in 2501,2502 } |
  Select-Object -First 5 TimeCreated, Id, Message
What to look for: If Get-DnsServerScavenging shows ScavengingState: False, or Get-DnsServerZoneAging shows AgingEnabled: False, that alone explains it — nothing has ever been eligible for cleanup. If both are enabled but you see no Event 2501/2502 at all, scavenging isn’t running on this server, not just this zone.

Common Causes

Cause How to Confirm Fix
Scavenging never enabled (server, zone, or both) Get-DnsServerScavenging and Get-DnsServerZoneAging show False. Enable both, following a phased rollout — see the fix below. Don’t enable blind.
DC was force-removed, not gracefully demoted No Netlogon deregistration ever ran; the A record and SRV entries never got a delete request. Delete the leftover records manually with Remove-DnsServerResourceRecord, and complete AD metadata cleanup if not already done.
Records were added or converted manually Time stamp on the record shows 0 in DNS Manager’s advanced view. Delete and let dynamic registration recreate it, or explicitly reset the time stamp.
Replication hasn’t converged since the DC left The zone’s directory partition hasn’t synced with a partner within the refresh interval; scavenging silently skips the zone. Confirm replication is healthy, complete metadata cleanup for the removed DC, and give it one more scavenging cycle.
Refresh + No-refresh interval is shorter than the client’s actual registration cadence Records for live, healthy machines are also disappearing — not just the decommissioned DC’s. Increase the intervals so their sum comfortably exceeds the longest DHCP lease or registration gap on the network.
Only one DNS server was cleaned, not all replicas Record is gone on one DNS server but reappears after AD replication. Delete on the AD-integrated zone once — it replicates. Don’t hand-edit a standard secondary zone.

Working Through a Fix

First, confirm the decommission itself is actually finished in Active Directory, not just DNS. If the DC was force-removed, run AD metadata cleanup before touching DNS — deleting the DNS records first, while the computer object and NTDS Settings object still exist, just gives Netlogon on another DC a reason to re-register them:

# From an elevated command prompt on a healthy DC
ntdsutil
metadata cleanup
connections
connect to server DC01
quit
select operation target
list domains
select domain 0
list sites
select site 0
list servers in site
select server 2
quit
remove selected server
quit
quit
Syntax note: remove selected server takes no argument — it acts on whatever target select operation target selected. The domain/site/server numbers come from the list output just before each select; they are not fixed values, so read the listed index for DC03 rather than assuming it is always 2.
Production note: Metadata cleanup removes the computer object, NTDS Settings, and replication links — it does not touch DNS. Using Active Directory Users and Computers or Active Directory Sites and Services to delete the DC’s objects performs the same cleanup with a GUI and is the supported alternative to raw ntdsutil commands.

With metadata cleanup confirmed, remove the leftover DNS records directly rather than waiting on scavenging, which can take weeks even when configured correctly:

# Delete the retired DC's host record
Remove-DnsServerResourceRecord -ZoneName corp.example.com `
  -Name "dc03" -RRType A -Force

# Delete its SRV records from the _msdcs zone (repeat for each SRV entry returned)
# -RecordData takes one array element per field - priority, weight, port, target -
# not a single space-separated string, or the cmdlet will not match the record.
Remove-DnsServerResourceRecord -ZoneName "_msdcs.corp.example.com" `
  -Name "_ldap._tcp.dc" -RRType Srv -RecordData "0","100","389","dc03.corp.example.com." -Force

# Delete its per-DC GUID CNAME under _msdcs
Remove-DnsServerResourceRecord -ZoneName "_msdcs.corp.example.com" `
  -Name "3f2504e0-4f89-11d3-9a0c-0305e82c3301" -RRType CName -Force

Then fix the underlying reason this required manual cleanup at all: turn on aging and scavenging properly, so the next decommission — graceful or not — cleans itself up without intervention.

# Enable scavenging on the server, with conservative default intervals
Set-DnsServerScavenging -ScavengingState $true `
  -ScavengingInterval 7.00:00:00 -ApplyOnAllZones

# Enable aging on the zone itself
Set-DnsServerZoneAging -Name corp.example.com -Aging $true `
  -RefreshInterval 7.00:00:00 -NoRefreshInterval 7.00:00:00

# Restrict which DNS servers actually perform scavenging - keep it to one
dnscmd /zoneresetscavengeservers corp.example.com 10.10.0.10
Practical rule: Enable scavenging on exactly one DNS server per AD-integrated zone. Every server hosting the zone can still see the results once they replicate, but only one needs to run the cleanup — that gives you one set of Event 2501/2502 logs to check instead of one per server.

How to Prevent It

If scavenging isn’t already running in the environment, don’t flip it on against a live zone without a dry run — Microsoft’s own guidance budgets four to five weeks for a first-time rollout: enable aging on the zone, wait out a full refresh-plus-no-refresh cycle, then audit for anything that still looks stale before you actually let a server delete records. A record that shouldn’t be there yet is a configuration bug worth finding before scavenging finds it for you.

Make DNS cleanup a mandatory line item in your decommission runbook, not an afterthought that scavenging is expected to catch eventually. A graceful Remove-ADDSDomainController handles most of it automatically, but confirm the SRV records and the _msdcs GUID CNAME are actually gone afterward — don’t assume. For any DC pulled from production by force, budget time immediately after for metadata cleanup followed by a manual DNS sweep, rather than waiting for a monitoring alert to surface the leftover records months later.

Quick Reference

Command / Event Use
Get-DnsServerScavengingCheck whether scavenging is enabled at the server level.
Get-DnsServerZoneAgingCheck whether aging is enabled for a specific zone.
Set-DnsServerScavenging / Set-DnsServerZoneAgingEnable and tune aging/scavenging at server and zone level.
Remove-DnsServerResourceRecordDelete a stale record immediately instead of waiting for scavenging.
dnscmd /zoneresetscavengeserversRestrict which DNS servers are allowed to scavenge a given zone.
Event 2501 / 2502 (DNS Server log)2501 = records deleted this cycle. 2502 = cycle ran, nothing deleted.
ntdsutil metadata cleanupRemove AD objects for a force-removed DC — required before its DNS records are safe to delete.

Final Thoughts

A decommissioned DC that lingers in DNS isn’t a sign anything is broken — it is DNS doing exactly what it was told, which is to leave records alone unless a specific, deliberate chain of conditions says otherwise. Aging and scavenging exist to make that cleanup automatic, but only once you’ve configured all three layers and given the process the replication safety margin it needs.

Treat DNS cleanup as part of the decommission itself, not a background job scavenging will eventually handle. When it doesn’t — because scavenging was never enabled, or the removal was forced — a few targeted Remove-DnsServerResourceRecord calls clear it immediately, and a properly configured scavenging pass keeps the next one from needing your attention at all.

Key takeaway: Check Get-DnsServerScavenging and Get-DnsServerZoneAging first — if either shows disabled, that’s the whole story. If both are enabled and records still linger, confirm AD metadata cleanup finished and replication has converged since; scavenging silently skips a zone until it has.
More troubleshooting

Stale or missing SRV records are also one of the causes behind “There are currently no logon servers available” — the client-side symptom of the same DC Locator chain this post cleans up from the DNS side.